开发者

Why can't I project ToString() in VB?

If you try to compile the query below in Visual Basic .NET, it fails.

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

The error given by the compiler is:

Range variable name cannot match the name of a member of the 'Object' class.

There is nothing wrong with the equivalent C# q开发者_如何学Pythonuery, though:

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

This does not happen with the ToString overload that takes a format (it is a member of Int32, not Object). It does happen with other members of Object, as long as they don't take an argument: with GetType and GetHashCode it fails; with Equals(object) it compiles.

Why is this restriction in place, and what alternatives can I use?


I couldn't tell you exacly why VB has this ridiculousness, but the simple workaround is to put the method call in parens.

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


Here's how I understand it. Consider the following code:

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

In the query above, the name of the Length variable is automatically "guessed" for you by the VB compiler based on the expression x.Length. Now, it's true that you didn't ask for this; it's just a feature that's provided whether you like it or not. But now consider this:

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

The above does not compile because the expression inside the first Select clause is not as simple as in the first case (believe it or not); the parentheses complicate matters just enough for the compiler not to pick the name Length; instead, it generates a name that is not usable from code.

So basically what's happening with ToString() is that this expression is simple enough for the compiler to use to generate a variable name, which could be used if the query were expanded to make use of this variable, e.g.:

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

However, ToString is not a legal name for a variable since it is a member of System.Object (why this would be the case for variables within LINQ queries but not for standard local variables, I couldn't say).


While I can't offer details about the error, a simple workaround it:

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

For what it's worth, when you have the following line:

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

it is compiles and decompiles to (using Reflector, to 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));
    }
}

There doesn't seem to be any anonymous class along the way.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜