Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

vb.net

linq

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?

like image 732
R. Martinho Fernandes Avatar asked Jan 10 '11 12:01

R. Martinho Fernandes


People also ask

What is ToString in Visual Basic?

ToString(Decimal, NumberFormatInfo) Converts a Decimal value to a String value, using the specified number format. ToString(UInt64) Converts a Ulong value to a String value.

How ToString works c#?

ToString returns a string that represents the current object. It is the main formatting method in . NET. The default implementation of the method returns the fully qualified name of the object's type.


3 Answers

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())
like image 145
tnyfst Avatar answered Oct 06 '22 13:10

tnyfst


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

like image 26
Dan Tao Avatar answered Oct 06 '22 12:10

Dan Tao


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.

like image 45
Kobi Avatar answered Oct 06 '22 14:10

Kobi