Я дивився на приклад коду C # і помітив, що один приклад обернув повернення в ().
Я завжди тільки що робив:
return myRV;
Чи є різниця робити:
return (myRV);
Відповіді:
ОНОВЛЕННЯ: Це питання було предметом мого блогу 12 квітня 2010 року . Дякую за кумедне запитання!
На практиці різниці немає.
В теорії не може бути різниця. У специфікації C # є три цікаві моменти, де це може спричинити різницю.
По-перше, перетворення анонімних функцій для делегування типів та дерев виразів. Розглянемо наступне:
Func<int> F1() { return ()=>1; }
Func<int> F2() { return (()=>1); }
F1
є явно законним. Є F2
? Технічно, ні. Специфікація говорить у розділі 6.5, що відбувається перетворення з лямбда-виразу на сумісний тип делегата. Це лямбда-вираз ? Ні. Це вираз у дужках, який містить лямбда-вираз .
Компілятор Visual C # робить тут невелике порушення специфікації та відкидає за вас дужки.
Друге:
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)
" не є буквальним нулем, це дужка, за якою слідує буквальний нуль, а потім дужка. Ми порушуємо специфікацію тут і фактично допускаємо будь-який вираз постійної часу компіляції, рівний нулю , а не лише буквальний нуль.
Тому в кожному випадку ми дозволяємо вам уникнути, хоча технічно це заборонено.
Бувають кутові випадки, коли наявність дужок може вплинути на поведінку програми:
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;
}
Сподіваюся, ви ніколи цього не побачите на практиці.
Хороший спосіб відповісти на подібні запитання - скористатися Reflector і подивитися, що генерується IL. Ви можете багато дізнатись про оптимізацію компілятора та подібні, розпакувавши збірки.