Patrzyłem na przykładowy kod C # i zauważyłem, że jeden przykład zawinął zwrot w ().
Zawsze robiłem:
return myRV;
Czy jest różnica w wykonywaniu:
return (myRV);
AKTUALIZACJA: To pytanie było tematem mojego bloga 12 kwietnia 2010 roku . Dzięki za zabawne pytanie!
W praktyce nie ma różnicy.
W teorii może istnieć różnica. W specyfikacji C # są trzy interesujące punkty, w których może to stanowić różnicę.
Po pierwsze, konwersja funkcji anonimowych na typy delegowane i drzewa wyrażeń. Rozważ następujące:
Func<int> F1() { return ()=>1; }
Func<int> F2() { return (()=>1); }
F1
jest wyraźnie legalne. Jest F2
? Technicznie nie. Specyfikacja mówi w sekcji 6.5, że następuje konwersja wyrażenia lambda na zgodny typ delegata. Czy to wyrażenie lambda ? Nie. To wyrażenie w nawiasach zawierające wyrażenie lambda .
Kompilator Visual C # dokonuje tutaj niewielkiego naruszenia specyfikacji i odrzuca za Ciebie nawias.
Druga:
int M() { return 1; }
Func<int> F3() { return M; }
Func<int> F4() { return (M); }
F3
jest legalne. Jest F4
? Nie. Sekcja 7.5.3 stwierdza, że wyrażenie w nawiasach nie może zawierać grupy metod. Ponownie, dla Twojej wygody naruszamy specyfikację i zezwalamy na konwersję.
Trzeci:
enum E { None }
E F5() { return 0; }
E F6() { return (0); }
F5
jest legalne. Jest F6
? Nie. Specyfikacja stwierdza, że następuje konwersja z literalnego zera do dowolnego typu wyliczeniowego. „ (0)
” nie jest dosłownym zerem, jest to nawias, po którym następuje dosłowne zero, po którym następuje nawias. Naruszamy tutaj specyfikację i faktycznie zezwalamy na dowolne wyrażenie stałej czasu kompilacji równe zero , a nie tylko dosłowne zero.
Dlatego w każdym przypadku pozwalamy ci ujść na sucho, nawet jeśli technicznie jest to nielegalne.
Istnieją przypadki narożne, w których obecność nawiasów może mieć wpływ na zachowanie programu:
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; }
Mam nadzieję, że nigdy nie zobaczysz tego w praktyce.
źródło
Nie, nie ma innej różnicy niż składnia.
źródło
Dobrym sposobem na udzielenie odpowiedzi na takie pytania jest użycie Reflectora i sprawdzenie, jakie IL jest generowane. Możesz dowiedzieć się wiele o optymalizacji kompilatora i tym podobnych, dekompilując zestawy.
źródło