如果您尝试在Visual Basic .NET中编译下面的查询,它将失败.
From x In {1, 2} Select x.ToString()
Run Code Online (Sandbox Code Playgroud)
编译器给出的错误是:
范围变量名称不能与"对象"类的成员名称匹配.
但是,等效的C#查询没有任何问题:
from x in new[]{1, 2} select x.ToString()
Run Code Online (Sandbox Code Playgroud)
ToString采用格式的重载(它是Int32的成员,而不是Object)不会发生这种情况.它使用对象的其他成员发生,只要他们不带任何参数:使用的GetType和GetHashCode失败; 使用Equals(对象)进行编译.
为什么会出现这种限制,我可以使用哪些替代方案?
tny*_*fst 36
我无法告诉你为什么 VB有这种荒谬,但简单的解决方法是将方法调用放在parens中.
Dim q = From x In {1, 2} Select (x.ToString())
Run Code Online (Sandbox Code Playgroud)
Dan*_*Tao 11
这是我理解它的方式.请考虑以下代码:
Dim q = From x In {"Bob", "Larry"}
Select x.Length
Select Length * 2
Run Code Online (Sandbox Code Playgroud)
在上面的查询中,VB编译器根据表达式自动 "猜测" Length变量的名称.现在,你没有要求这个; 它只是一个功能,无论你喜欢与否.但现在考虑一下:x.Length
Dim q = From x In {"Bob", "Larry"}
Select (x.Length)
Select Length * 2
Run Code Online (Sandbox Code Playgroud)
上面的代码没有编译,因为第一Select个子句中的表达式并不像第一种情况那样简单(信不信由你); 括号使事情变得复杂,以至于编译器不会选择名称Length; 相反,它生成一个不能从代码中使用的名称.
所以基本上与发生的事情ToString()是,这个表达式是很简单的编译器使用,以产生一个变量名,它可能如果查询扩大到使用这个变量,例如可以使用:
Dim q = From x In { 1, 2 }
Select x.ToString()
Select ToString.Length
Run Code Online (Sandbox Code Playgroud)
但是,ToString它不是变量的合法名称,因为它是一个成员System.Object(为什么LINQ查询中的变量会出现这种情况,但对于标准局部变量则不然,我不能说).
虽然我无法提供有关错误的详细信息,但有一个简单的解决方法:
From x In {1, 2, 3} Let str = x.ToString() Select str
Run Code Online (Sandbox Code Playgroud)
当你有以下几行时,它的价值是多少:
Dim b = From num In {1, 2, 3} Select num.ToString("d")
Run Code Online (Sandbox Code Playgroud)
它是编译和反编译(使用Reflector,C#):
public class Class1
{
[CompilerGenerated]
private static string _Lambda$__1(int num)
{
return num.ToString("d");
}
public void Test1()
{
IEnumerable<string> b = new int[] { 1, 2, 3 }
.Select<int, string>(new Func<int, string>(Class1._Lambda$__1));
}
}
Run Code Online (Sandbox Code Playgroud)
沿途似乎没有任何匿名课程.