Есть ли разница между return myVar и return (myVar)?

Я смотрел пример кода на С# и заметил, что один пример завернул return в().

Я всегда делал:

return myRV;

Есть ли разница:

return (myRV);

Ответ 1

UPDATE: этот вопрос был тема моего блога 12 апреля 2010 года. Спасибо за забавный вопрос!

На практике нет разницы.

В теории может быть разница. В спецификации С# есть три интересных момента, где это может привести к различию.

Во-первых, преобразование анонимных функций для делегирования типов и деревьев выражений. Рассмотрим следующее:

Func<int> F1() { return ()=>1; }
Func<int> F2() { return (()=>1); }

F1 является явно законным. Является F2? Технически, нет. Спецификация говорит в разделе 6.5, что есть преобразование из лямбда-выражения в совместимый тип делегата. Это лямбда-выражение? Нет. Это выражение в скобках, содержащее лямбда-выражение.

Компилятор Visual С# делает здесь небольшое нарушение спецификации и отбрасывает скобки для вас.

Во-вторых:

int M() { return 1; }
Func<int> F3() { return M; }
Func<int> F4() { return (M); }

F3 является законным. Является F4? Нет. В разделе 7.5.3 указано, что выражение в скобках не может содержать группу методов. Опять же, для вашего удобства мы нарушаем спецификацию и разрешаем преобразование.

Третье:

enum E { None }
E F5() { return 0; }
E F6() { return (0); }

F5 является законным. Является F6? Нет. Спецификация заявляет, что есть преобразование из буквального нуля в любой перечислимый тип. "(0)" не является буквальным нулем, это скобка, за которой следует буквальный нуль, за которым следует скобка. Мы нарушаем спецификацию здесь и фактически разрешаем любое выражение постоянной времени компиляции равным нулю, а не только буквальное значение.

Таким образом, в каждом случае мы позволяем вам уйти от него, хотя технически это незаконно.

Ответ 2

Существуют угловые случаи, когда наличие скобок может влиять на поведение программы:

1.

using System;

class A
{
    static void Foo(string x, Action<Action> y) { Console.WriteLine(1); }
    static void Foo(object x, Func<Func<int>, int> y) { Console.WriteLine(2); }

    static void Main()
    {
        Foo(null, x => x()); // Prints 1
        Foo(null, x => (x())); // Prints 2
    }
}

2.

using System;

class A
{
    public A Select(Func<A, A> f)
    {
        Console.WriteLine(1);
        return new A();
    }

    public A Where(Func<A, bool> f)
    {
        return new A();
    }

    static void Main()
    {
        object x;
        x = from y in new A() where true select (y); // Prints 1
        x = from y in new A() where true select y; // Prints nothing
    }
}

3.

using System;

class Program
{
    static void Main()
    {
        Bar(x => (x).Foo(), ""); // Prints 1
        Bar(x => ((x).Foo)(), ""); // Prints 2
    }

    static void Bar(Action<C<int>> x, string y) { Console.WriteLine(1); }
    static void Bar(Action<C<Action>> x, object y) { Console.WriteLine(2); }
}

static class B
{
    public static void Foo(this object x) { }
}

class C<T>
{
    public T Foo;
}

Надеюсь, вы никогда не увидите этого на практике.

Ответ 3

Нет, нет никакой разницы, кроме синтаксической.

Ответ 4

Хороший способ ответить на такие вопросы, как использовать Reflector и посмотреть, что IL генерирует. Вы можете много узнать о оптимизации компилятора и, например, декомпилировать сборки.