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