为什么我不能在VB中投影ToString()?

时间:2011-01-10 12:18:06

标签: vb.net linq

如果您尝试在Visual Basic .NET中编译下面的查询,则会失败。

From x In {1, 2} Select x.ToString()

编译器给出的错误是:

  

范围变量名称不能与“对象”类的成员名称匹配。

但是,等效的C#查询没有任何问题:

from x in new[]{1, 2} select x.ToString()

对于采用格式的ToString重载(它是Int32的成员,而不是Object),不会发生这种情况。它确实发生在Object的其他成员身上,只要它们不接受参数:使用GetType和GetHashCode就会失败;使用Equals(object)进行编译。

为什么会出现这种限制,我可以使用哪些替代方案?

3 个答案:

答案 0 :(得分:35)

我无法告诉你为什么 VB有这种荒谬,但简单的解决方法是将方法调用放入parens。

Dim q = From x In {1, 2} Select (x.ToString())

答案 1 :(得分:11)

以下是我的理解方式。请考虑以下代码:

Dim q = From x In {"Bob", "Larry"}
        Select x.Length
        Select Length * 2

在上面的查询中,VB编译器根据表达式Length为您自动“猜测”{em} “猜测”x.Length变量的名称。现在,你确实没有这个;它只是一个功能,无论你喜欢与否。但现在考虑一下:

Dim q = From x In {"Bob", "Larry"}
        Select (x.Length)
        Select Length * 2

上面没有编译,因为第一个Select子句中的表达式并不像第一种情况那样简单(信不信由你);括号使问题变得复杂,以至于编译器不能选择名称Length;相反,它会生成一个代码无法使用的名称。

所以基本上ToString()发生的事情是这个表达式很简单,编译器可以用它来生成一个变量名,如果扩展查询以便使用可以这个变量,例如:

Dim q = From x In { 1, 2 }
        Select x.ToString()
        Select ToString.Length

但是,ToString不是变量的合法名称,因为它是System.Object的成员(为什么LINQ查询中的变量会出现这种情况,但对于标准局部变量则不然,我不能不说。)

答案 2 :(得分:5)

虽然我无法提供有关错误的详细信息,但有一个简单的解决方法:

From x In {1, 2, 3} Let str = x.ToString() Select str

当你拥有以下一行时,它的价值是什么:

Dim b = From num In {1, 2, 3} Select num.ToString("d")

它编译并反编译为(使用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));
    }
}

沿途似乎没有任何匿名课程。