将算法从 C# 转换为 VB.NET 失败
我正在尝试将以下算法从 C# 转换为 VB.NET,但我所拥有的 VB.NET 产生的结果与我的 C# 算法不同,有人可以告诉我在转换过程中哪里出了问题吗?
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;
}
这就是我在 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
出了点问题,但我不确定是什么,我猜问题出在 lambda 中的某个地方。
有人能指出我的转换做错了什么吗?
I'm trying to convert the following algorithm from C# to VB.NET and the VB.NET I have is not producing the same results as my C# algorithm, can someone tell me where I've gone wrong 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;
}
This is what I've 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 what, I'm guessing the problem is somewhere in the lambda.
Can anybody point out what I've done wrong with my conversion?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用代码转换器...
Use a code converter...
我根本不是 VB 专家,但问题可能源于以下任一原因:
current = current + 1
与current++
不同。它(基本上)与++current
相同。它们有不同的行为。由于 VB 不直接支持内联后递增运算符,我能想到的最接近的无错误实现是(在 C# 中,因为我不知道 VB):
或者,它可能源于:
当我使用 .Net Reflector 时看看它并将其“转换”为 VB,
elements
似乎是ByVal
。I'm no expert on VB at all, but the problem might stem from either:
current = current + 1
is not the same ascurrent++
. It is (basically) the same as++current
. These have way different behavior.Since VB doesn't support inline post-increment operators directly, the closest bug-free implementation I can think of is (in C#, since I don't know VB):
Or, it could stem from:
When I use .Net Reflector to look at it and "convert" it to VB,
elements
seems to beByVal
.据我所知,根本不需要就地增加电流。只需在 Linq 表达式之后增加它即可。另一方面,您应该使用
1
初始化current
,与 C# 中相同。此外,你的“基本情况”有点奇怪;你可以这样写:
不需要
-1
。There’s no need for the in-place increment of current at all, as far as I can see. Just increment it after the Linq expression. On the other hand, you should initialise
current
with1
, same as in C#.Furthermore, your “base case” is a bit weird; you can just write this:
No need for the
-1
.我手头没有编译器来检查,但我会像这样转换它:
这是我现在能想到的每个语法元素的直接转换。一旦你让它工作,然后考虑清理它(例如尝试消除 LINQ 表达式的副作用)。
编辑:
与您的代码的差异:
New T(-1) {}
应为New T() {}
。current
应初始化为 1 而不是 0。Skip(current = current + 1)
不会执行您想要的操作。事实上,它什么也不做,因为current = current + 1
是一个布尔表达式,其计算结果始终为 false。如果选项 strict 关闭,VB.NET 将默默地将 false 转换为 0;如果选项 strict 打开,则抛出编译器错误。I don't have a compiler on hand to check, but I would convert it like this:
That's as direct a conversion of each syntax element as I can think of right now. Once you have it working, then think about cleaning it up (e.g. try to remove side effects from the LINQ expression).
EDIT:
Differences from your code:
New T(-1) {}
should beNew T() {}
.current
should be initialised to 1 not 0.Skip(current = current + 1)
will not do what you want. In fact, it does nothing, becausecurrent = current + 1
is a boolean expression that will always evaluate to false. VB.NET will silently convert false to 0 if option strict is off, or throw a compiler error if option strict is on.