Estaba mirando un ejemplo de código C # y noté que un ejemplo envolvía la devolución en ().
Siempre acabo de hacer:
return myRV;
¿Hay alguna diferencia al hacer:
return (myRV);
Respuestas:
ACTUALIZACIÓN: Esta pregunta fue el tema de mi blog el 12 de abril de 2010 . ¡Gracias por la divertida pregunta!
En la práctica, no hay diferencia.
En teoría , podría haber una diferencia. Hay tres puntos interesantes en la especificación de C # donde esto podría presentar una diferencia.
Primero, la conversión de funciones anónimas para delegar tipos y árboles de expresión. Considera lo siguiente:
Func<int> F1() { return ()=>1; }
Func<int> F2() { return (()=>1); }
F1
es claramente legal. Es F2
? Técnicamente, no. La especificación dice en la sección 6.5 que hay una conversión de una expresión lambda a un tipo de delegado compatible. ¿Es esa una expresión lambda ? No. Es una expresión entre paréntesis que contiene una expresión lambda .
El compilador de Visual C # hace una pequeña infracción de especificación aquí y descarta el paréntesis por usted.
Segundo:
int M() { return 1; }
Func<int> F3() { return M; }
Func<int> F4() { return (M); }
F3
es legal. Es F4
? No. La sección 7.5.3 establece que una expresión entre paréntesis no puede contener un grupo de métodos. Nuevamente, para su conveniencia, violamos la especificación y permitimos la conversión.
Tercero:
enum E { None }
E F5() { return 0; }
E F6() { return (0); }
F5
es legal. Es F6
? No. La especificación establece que hay una conversión del literal cero a cualquier tipo enumerado. " (0)
" no es el cero literal, es un paréntesis seguido del cero literal, seguido de un paréntesis. Aquí violamos la especificación y de hecho permitimos cualquier expresión constante de tiempo de compilación igual a cero , y no solo cero literal.
Entonces, en todos los casos, le permitimos salirse con la suya, aunque técnicamente hacerlo es ilegal.
Hay casos extremos en los que la presencia de paréntesis puede afectar el comportamiento del programa:
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;
}
Espero que nunca veas esto en la práctica.
Una buena forma de responder preguntas como esta es usar Reflector y ver qué IL se genera. Puede aprender mucho sobre las optimizaciones del compilador y demás descompilando ensamblados.