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
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.
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())