var en c# si, o var no
Este es de esos post donde uno piensa exactamente igual que cuando deshoja una margarita. Me quiere no me quiere. Mi opinión antes de seguir es que la quiero:).
Todo esto surge a raíz de una conversación en twitter que podéis seguir aquí y que lógicamente expuso diferentes opiniones que al final es en lo que consiste, Yo opino, tu opinas.
¿Quien tiene la razón? todos:).
Un poco de puesta en escena
https://twitter.com/#!/_PedroHurtado/status/202057547094564864, claro yo haciendo caso omiso a los consejos de mi padre “Pedro Dios te dio dos orejas para escuchar el doble de lo que hablas”. No se me ocurre otra cosa que lanzar esto:).
https://twitter.com/#!/_PedroHurtado/status/202058984570621953 y después no conforme con esto un poco más de fuerza bruta.
https://twitter.com/#!/_PedroHurtado/status/202060219935756288
Con lo cual surge todo esto.
https://twitter.com/#!/_PedroHurtado/status/202061813746110464 y más. Que no es necesario hacerse pesado y vamos al grano.
Que es var?
De las pocas cosas que da gusto leer en el MSND y uno se entera. Es la definición de Variables locales con asignación implícita de tipos (Guía de programación de C#).
Pero si nos centramos en esto vemos cosas que deberían tener algún que otro comentario.
“A las variables locales se les puede asignar un "tipo" deducido var en lugar de un tipo explícito. La palabra clave var indica al compilador que deduzca el tipo de la variable a partir de la expresión que se encuentra en el lado derecho de la instrucción de inicialización”
Efectivamente Eduard(@eiximenis), discrepo totalmente en tu afirmación “cuando el tipo del lvalue es distinto al tipo del rvalue... ;)” no creo que lvalue entendido como la parte izquierda sea distinto jamás al rvalue es decir el lvalue es deducido o mejor dicho inferido a partir del rvalue, con lo cual todo es valido para “var” y lo vamos a ver:).
@Jonathan_JFR, te voy a explicar porque los tipos anónimos o lambda expresion no se pueden inferir, para ello te recomiendo esta lectura Why can't an anonymous method be assigned to var?. En la cual el gran Eric Lippert metió la pata hasta donde se puede meter:), me quedo con la respuesta de Mehrdad.
“@Eric: Good answer, but it's slightly misleading to illustrate this as something that's not possible, as this actually works completely fine in D. It's just that you guys didn't choose to give delegate literals their own type, and instead made them depend on their contexts... so IMHO the answer should be "because that's how we made it" more than anything else. :)”
Pues si Eriq es confuso y te voy a poner un ejemplo sencillo.
var i = 123;
Esto que es?
Un int,uint,short,ushort,long,ulong,sbyte,byte
¿Por qué se infiere un int?
Creo que “porque así se decidió”.
Con lo cual tu para inferir un "tipo integrado” o un ValueType te tienes que ir a la siguiente tabla.
Tabla de valores predeterminados (Referencia de C#).
En resumen si yo quiero hacer que i sea del tipo Decimal tengo que hacer esto.
var i=123M; o bien var i = 123m; es decir hacer uso de los Literales y más concretamente de los sufijos de estos o bien en el caso de short que no lo tiene hacer uso de lo siguiente.
var i=(short)0;
A partir de este momento es fácil deducir como una Lambda Expresion o bien un Método Anónimo lo puedo poner a la derecha de “var”.
1: var i = delegate(int y) //Error No se puede asignar metodo anonimo a una variable local tipificada implicitamente
2: {
3: return y * 2;
4: };
5: var i = ((Func<int,int>)delegate(int y) //Ok
6: {
7: return y * 2;
8: });
Ahora vamos con las Lambda Expresion, estás pueden devolver o un Func,etc,etc o bien o una Expresión es decir esto sería un Func.
1: Func<int, int, int> b = (x,y)=>x*y;
o eso mismo podría ser
1: Expression<Func<int, int, int>> b = (x, y) => x * y;
Alguien me impide a mi hacer esto.
1: var i = (int x, int y) => x * y;
Si el compilador, pero que ocurre si hago lo siguiente, pues que todo funciona.
1: var i = (Func<int,int,int>)((x,y)=>x+y);
2: var resultado = i(10, 10);
3: Console.WriteLine(i.GetType());
4: Console.WriteLine(resultado.GetType());
5: Console.WriteLine(resultado);
Os imagináis el resultado, pues os lo muestro.
System.Func`3[System.Int32,System.Int32,System.Int32]
System.Int32
20
Otra cosa, puede hacer esto?.
var i = null, pues no y para ello lo mejor que podemos es revisar lo siguiente. Implicitly Typed Local Variables, concretamente el apartado de “restrictions”.
Pues sí puedo hacer y muchas cosas más.
1: var nullint32 =(int?)0;
2: var nulo = (Clase)null;
3: var xByte = (byte)0;
4: var Xdecimal= 0M;
5: var XLong = 0L;
6: var XDouble = 0D;
7: var XUint = 0U;
8: var XShort = 0;
9: var xFloat = 0F;
10: var XChar = '1';
11: var XEnum = (aaa)1;
12: var xShort = (short)32767;
Y de esta forma todas las que se os ocurran:).
Conclusiones.
1. Que como todo tiene su razón de ser, que se puede utilizar y ahorrar trabajo es evidente.
2. Que si abusamos puede llegar a ser malo, también.
3. Yo lo utilizo siempre en linq, tipos anonimos,al crear un nuevo objeto, en using,devoluciones de metodos y foreach y hasta el momento no he tenido ningún problema.
4. Es el Dim de Vb. Nooooooooooooooo.
5. Es un variant de vb o bien un object de c#. Nooooooooo, si revisamos el IL vemos que exactamente tanto una como la otra sentencia genera lo mismo.
int i = 10;
var i=10;
6. Es confuso Noooooooooo, para mi confuso es no poner nombres claros a las variables, eso si que es confuso.