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# query, 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?
Here’s how I understand it. Consider the following code:
In the query above, the name of the
Lengthvariable is automatically “guessed” for you by the VB compiler based on the expressionx.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:The above does not compile because the expression inside the first
Selectclause 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 nameLength; 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.:However,
ToStringis not a legal name for a variable since it is a member ofSystem.Object(why this would be the case for variables within LINQ queries but not for standard local variables, I couldn’t say).