Converting an algorithm from C # to VB.NET crashes

I am trying to convert the following algorithm from C # to VB.NET and VB.NET, which I have, does not produce the same results as my C # algorithm, can someone tell me where I made a mistake in my conversion?

public static IEnumerable<T[]> Combinations<T>(this IEnumerable<T> elements, int k) { List<T[]> result = new List<T[]>(); // single combination if (k == 0) { result.Add(new T[0]); } else { int current = 1; foreach (T element in elements) { //combine each element with k-1 combinations of subsequent elements result.AddRange(elements .Skip(current++) .Combinations(k - 1) .Select(combination => (new T[] { element }).Concat(combination).ToArray()) ); } } return result; } 

Here is what I got in VB.NET:

 <Extension()> Public Function Combinations(Of T)(ByRef elements As IEnumerable(Of T), ByVal k As Integer) As IEnumerable(Of T()) Dim result As New List(Of T())() 'single combination' If k = 0 Then result.Add(New T(-1) {}) Else Dim current As Integer = 0 For Each element As T In elements 'combine each element with k - 1 combinations of subsequent elements' Dim local As T = element result.AddRange(elements.Skip(current = current + 1).Combinations(k - 1).Select(Function(combs) (New T() {local}).Concat(combs).ToArray())) Next End If Return result End Function 

Something is wrong, but I'm not sure that, I assume the problem is somewhere in lambda.

Can anyone point out what I did wrong with my conversion?

+4
source share
4 answers

Use the code converter ...

 <System.Runtime.CompilerServices.Extension> _ Public Shared Function Combinations(Of T)(elements As IEnumerable(Of T), k As Integer) As IEnumerable(Of T()) Dim result As New List(Of T())() ' single combination If k = 0 Then result.Add(New T(-1) {}) Else Dim current As Integer = 1 For Each element As T In elements 'combine each element with k-1 combinations of subsequent elements result.AddRange(elements.Skip(System.Math.Max(System.Threading.Interlocked.Increment(current),current - 1)).Combinations(k - 1).[Select](Function(combination) (New T() {element}).Concat(combination).ToArray())) Next End If Return result End Function 
+2
source

I'm not a VB specialist at all, but the problem may be related to:

current = current + 1 does not match current++ . This is (basically) the same as ++current . They have a different behavior.

Since VB does not support immediate post-increment operators, the nearest error-free error I can think of (in C # since I don't know VB):

 int current = 0; Func<int> getCurrentThenIncrement = () => { int previous = current; current = current + 1; return previous; }; // ... .Skip(getCurrentThenIncrement()) 

Or it may be due to:

 Public Function Combinations(Of T)(ByRef elements ... 

When I use .Net Reflector to look at it and "convert" it to VB, the elements seem to be ByVal .

0
source

It seems to me that there is no need for an increase in current in place. Just increase it after the Linq expression. On the other hand, you must initialize current with 1 , as in C #.

Also, your โ€œbase caseโ€ is a bit odd; you can simply write this:

 result.Add(New T() { }) 

No need for -1 .

0
source

I do not have a compiler to test, but I would convert it as follows:

 <Extension()> Public Function Combinations(Of T)(elements As IEnumerable(Of T), k As Integer) As IEnumerable(Of T()) Dim result As New List(Of T())() ' single combination If k = 0 Then result.Add(New T() {}) Else Dim current As Integer = 1 For Each element As T In elements 'combine each element with k-1 combinations of subsequent elements result.AddRange(elements .Skip(PostfixInc(current)) .Combinations(k - 1) .Select(Function(combination) (New T() { element }).Concat(combination).ToArray()) ) Next End If Return result End Function Private Function PostfixInc(ByRef value As Integer) As Integer Dim currentValue = value value += 1 Return currentValue End Function 

This is like a direct conversion of every syntax element that I can think of right now. As soon as you earn it, consider cleaning it up (for example, try removing side effects from the LINQ expression).

EDIT:

Differences from your code:

  • New T(-1) {} must be New T() {} .
  • current must be initialized 1 not 0.
  • Skip(current = current + 1) will not do what you want. In fact, it does nothing, because current = current + 1 is a logical expression that will always evaluate to false. VB.NET silently converts false to 0 if the strict parameter is turned off or it generates a compiler error if the strict parameter is turned on.
0
source

All Articles