Подтвердить что ты не робот

Почему я не могу проектировать ToString() в VB?

Если вы попытаетесь скомпилировать запрос ниже в Visual Basic.NET, это не сработает.

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

Ошибка компилятора:

Имя переменной диапазона не может совпадать с именем члена класса Object.

Нет ничего плохого в эквивалентном запросе С#:

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

Это не происходит с перегрузкой ToString, которая принимает формат (это член Int32, а не Object). Это происходит с другими членами Object, если они не принимают аргумента: с GetType и GetHashCode он терпит неудачу; с помощью Equals (object), который он компилирует.

Почему это ограничение на месте и какие альтернативы я могу использовать?

4b9b3361

Ответ 1

Вот как я это понимаю. Рассмотрим следующий код:

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

В вышеприведенном запросе имя переменной Length автоматически "угадывается" для вас компилятором VB на основе выражения x.Length. Теперь, правда, вы не просили об этом; это просто функция, предоставляемая независимо от того, нравится вам это или нет. Но теперь рассмотрим это:

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

Вышеприведенное не компилируется, потому что выражение внутри первого предложения Select не так просто, как в первом случае (верьте или нет); скобки затрудняют дело, достаточное для того, чтобы компилятор не выбрал имя Length; вместо этого он генерирует имя, которое не может использоваться из кода.

Итак, в основном, что происходит с ToString(), заключается в том, что это выражение достаточно просто, чтобы компилятор мог использовать для генерации имени переменной, которое можно было использовать, если запрос был расширен, чтобы использовать эту переменную, например:

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

Однако ToString не является юридическим именем переменной, так как он является членом System.Object (почему это будет иметь место для переменных в запросах LINQ, но не для стандартных локальных переменных, я не мог сказать).

Ответ 2

Я не мог сказать вам, почему VB имеет эту смехотворность, но простым обходным путем является вызов метода в parens.

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

Ответ 3

Пока я не могу предложить подробную информацию об ошибке, просто обходное решение:

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

Для чего это стоит, когда у вас есть следующая строка:

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

он компилируется и декомпилируется (используя Reflector, С#):

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));
    }
}

На этом пути, похоже, нет анонимного класса.