practices net guidelines documentacion convenciones coding codigos codigo code classes best basicos c# coding-style implicit-typing

net - convenciones de codigo c#



¿Por qué var sería una mala cosa? (17)

He estado chateando con mis colegas el otro día y escuché que su estándar de codificación explícitamente les prohíbe usar la palabra clave var en C #. No tenían idea de por qué era así y siempre he encontrado que la declaración implícita es increíblemente útil cuando se codifica. Nunca tuve problemas para averiguar qué tipo era la variable (solo se desplaza sobre la variable en VS y obtendrá el tipo de esa manera).

¿Alguien sabe por qué sería una mala idea usar la palabra clave var en C #?


En la mayoría de los casos, cuando se usa con sensatez (es decir, un inicializador de tipo simple donde el tipo y el valor son los mismos), entonces está bien.

Hay momentos en los que no está claro que ha roto las cosas cambiándolo, principalmente, cuando el tipo inicializado y el tipo de variable (original) no son los mismos, porque:

  • la variable era originalmente la clase base
  • la variable era originalmente una interfaz
  • la variable era originalmente otro tipo con un operador de conversión implícito

En estos casos, puede tener problemas con cualquier resolución de tipo, por ejemplo:

  • métodos que tienen diferentes sobrecargas para los dos tipos de competencia
  • métodos de extensión que se definen de manera diferente para los dos tipos de competencia
  • miembros que han sido re-declarados (ocultos) en uno de los tipos
  • la inferencia de tipo genérico funcionará de manera diferente
  • la resolución del operador funcionará de manera diferente

En tales casos, cambia el significado del código y ejecuta algo diferente. Esto es algo malo.

Ejemplos:

Conversión implícita:

static void Main() { long x = 17; Foo(x); var y = 17; Foo(y); // boom } static void Foo(long value) { Console.WriteLine(value); } static void Foo(int value) { throw new NotImplementedException(); }

Método de ocultación:

static void Main() { Foo x = new Bar(); x.Go(); var y = new Bar(); y.Go(); // boom } class Foo { public void Go() { Console.WriteLine("Hi"); } } class Bar : Foo { public new void Go() { throw new NotImplementedException(); } }

etc


Escribí un artículo de blog sobre este tema hace unos meses. Para mí, lo uso en todos los casos posibles y específicamente diseño mis API en torno a la inferencia de tipo. Las razones básicas por las que uso la inferencia de tipo son

  1. No reduce la seguridad del tipo
  2. De hecho, aumentará la seguridad de tipo en su código al alertarlo sobre conversiones implícitas. El mejor ejemplo en la declaración foreach
  3. Mantiene principios DRY en C #. Esto es específicamente para el caso de declaración, ¿por qué molestarse en decir el nombre dos veces?
  4. En algunos casos es necesario. Ejemplo de tipos anónimos
  5. Menos tipeo sin pérdida de funcionalidad.

http://blogs.msdn.com/jaredpar/archive/2008/09/09/when-to-use-type-inference.aspx


Este es realmente un problema de legibilidad con su código.

Mi preferencia personal es usar siempre "var" para tipos anónimos (de hecho, si desea utilizar tipos anónimos, deberá usar var), y estos provienen principalmente de consultas LINQ. En estos casos, no tiene más remedio que usar var si su consulta se está proyectando en un tipo nuevo (implícito y anónimo).

Sin embargo, C # 3.0 con gusto te permitirá usar var en cualquier lugar que desees, fuera de LINQ y tipos anónimos, por ejemplo:

var myint = 0; var mystring = "";

es perfectamente válido, y myint y mystring estarán fuertemente tipados por los valores inferidos utilizados para inicializarlos. (por lo tanto, myint es un System.Int32 y mystring es un System.String). Por supuesto, es bastante obvio cuando miramos los valores utilizados para inicializar las variables a qué tipos se escribirán implícitamente, sin embargo, creo que es incluso mejor para la legibilidad del código si lo anterior se escribió como:

int myint = 0; string mystring = "";

ya que puede ver inmediatamente de un vistazo exactamente qué tipo de esas variables son.

Considere este escenario algo confuso:

var aaa = 0; double bbb = 0;

Código perfectamente válido (si bien poco convencional) pero en el anterior, sé que bbb es un doble, a pesar de que el valor de inicialización parece ser un int, pero aaa definitivamente no será un doble, sino un int.


He tenido casos (cuando foreach a través de una colección Table.Rows) cuando se utiliza var resultó en el tipo que es de alguna clase base en lugar del tipo de DataRow real. Esa es la única vez que he tenido problemas con var.


La tipificación implícita es excelente, y las personas que lo bloquean a fondo no permiten que se dañe la productividad e invitan al código frágil.

Es casi como tipificación segura, comprobada por el compilador, que es increíblemente útil cuando se refactoriza. Por ejemplo, si tengo un método que devuelve una Lista, y lo refactorizo ​​para que devuelva IEnumerable, cualquier persona que llame a ese método que haya usado la palabra clave var y solo use métodos IEnumerable estará bien. Si he especificado explícitamente, por ejemplo, Lista, entonces tengo que ir y cambiar eso a IEnumerable en todas partes.

Obviamente, si alguno de los llamadores de tipeo implícito requiere métodos de lista, obtendré errores de compilación cuando construyo, pero si ese es el caso, probablemente no debería haber cambiado el tipo de devolución de todos modos.


Primero, como regla general, los estándares de codificación deben ser discutidos y acordados por el equipo, y el razonamiento detrás de ellos debe escribirse, para que cualquiera pueda saber por qué están allí. No deberían ser la Santa Verdad de un Maestro.

En segundo lugar, esta regla probablemente esté justificada porque el código es más leído que escrito . var acelera la escritura, pero puede ralentizar la lectura un poco. Obviamente no es una regla de comportamiento del código como "Inicializar siempre variables" porque las dos alternativas (escribir var y escribir el tipo) tienen exactamente el mismo comportamiento. Entonces no es una regla crítica. No prohibiría var , solo usaría "Prefiero ..."


Prohibirlo significa prohibir el uso de tipos anónimos (que se vuelven increíblemente útiles a medida que usas LINQ más).

Esto es una estupidez simple y llana a menos que alguien pueda formalizar una buena razón para nunca usar tipos anónimos.


Puede dañar la legibilidad si se usa mal. Sin embargo, es completamente extraño, ya que a sus colegas les resultará difícil utilizar tipos anónimos sin él.


Seguramente esto es un error. Es porque algunas personas no se dan cuenta de que en realidad está fuertemente tipado, y en absoluto como una var en VB.

No todos los estándares de codificación corporativa tienen sentido, una vez trabajé para una compañía que quería ponerle un nombre a todos los nombres de clase. Hubo un gran retrabajo cuando la empresa cambió su nombre.


var es el último debate sobre "cómo diseñar sus brackets" / notación húngara / Camel casing. No hay una respuesta correcta, pero hay personas que se sientan en los extremos.

Tu amigo es desafortunado porque trabajan debajo de uno de los extremistas.


var q = GetQValue();

de hecho es algo malo. Sin embargo,

var persistenceManager = ServiceLocator.Resolve<IPersistenceManager>();

está perfectamente bien para mí.

La línea de fondo es: use nombres de identificación descriptivos y se llevará bien.

Como nota al margen: me pregunto cómo lidian con los tipos anónimos cuando no se les permite usar la palabra clave var . ¿O no los usan por completo?


Los redactores de .Net Framework Design Guidelines (awesome book) que salieron en noviembre de 2008 recomiendan considerar el uso de var cuando el tipo es obvio e inequívoco.

Por otro lado, si usar var pudiera resultar en una ambigüedad al leer el código, como señaló Anton Gogolev, entonces es mejor no usarlo.

en el libro (Anexo A), realmente dan este ejemplo:

var names = new List<string>(); // good usage of var string source = GetSource(); var tokens = source.Split('' ''); // ok; most developers know String.Split var id = GetId(); // Probably not good; it''s not clear what the type of id is

Es posible que, para garantizar que la legibilidad no esté sujeta a los caprichos de los desarrolladores humildes, su organización haya decidido que usted no era digno de var y lo prohibió.
Sin embargo, es una lástima, es como tener una buena herramienta a su disposición, pero mantenerla en un armario de vidrio cerrado con llave.

En la mayoría de los casos, usar var para tipos simples en realidad ayuda a la legibilidad y no debemos olvidar que tampoco hay una penalización en el rendimiento por usar var .


Aquí están los resultados de una prueba que realicé en eficiencia de var versus tipeo explícito:

private void btnVar_Click(object sender, EventArgs e) { Stopwatch obj = new Stopwatch(); obj.Start(); var test = "Test"; test.GetType(); obj.Stop(); lblResults.Text = obj.Elapsed.ToString(); } private void btnString_Click(object sender, EventArgs e) { Stopwatch obj = new Stopwatch(); obj.Start(); string test = "Test"; obj.Stop(); lblResults.Text = obj.Elapsed.ToString(); }

El resultado de la primera etiqueta es: 00:00:00 000034

El resultado de la segunda etiqueta es: 00:00:00 00008


Eric Lippert lo resume bien :

  • Usa var cuando tengas que hacerlo; cuando usa tipos anónimos
  • Use var cuando el tipo de declaración sea obvio desde el inicializador, especialmente si es una creación de objeto. Esto elimina la redundancia.
  • Considere usar var si el código enfatiza el "propósito comercial" semántico de la variable y minimiza los detalles "mecánicos" de su almacenamiento.
  • Use tipos explícitos si hacerlo es necesario para que el código se entienda y mantenga correctamente.
  • Use nombres de variables descriptivos independientemente de si usa "var". Los nombres de variables deben representar la semántica de la variable, no los detalles de su almacenamiento; "decimalRate" es malo; "interestRate" es bueno.

Mi propia opinión: me resulta más difícil de leer y un poco inútil con tipos como int , string , bool o incluso un User . Se trata de la legibilidad después de todo (excepto cuando se usa con LINQ), por lo que cuando se salpican los vars puede ser más difícil de leer y anular el propósito de la palabra clave para la que los diseñadores del lenguaje lo intentaron.


''var'' se trata de ser claro

El principal debate sobre si se debe usar la palabra clave var o no es sobre qué tan legible es el código para usted y para otros desarrolladores.

Como si estuvieras escribiendo una historia, no hay una respuesta correcta definitiva. Pero veamos algunos ejemplos de esto en inglés simple.

Jake saludó a Bill. No le gustaba así que se giró y se fue por el otro lado.

¿Quién fue por el otro lado? ¿Jake o Bill? En este caso, "Jake" y "Bill" son como el nombre del tipo. Y "Él" y "él" son como la palabra clave var. En este caso, podría ser más específico. Lo siguiente, por ejemplo, es mucho más claro.

Jake saludó a Bill. A Jake no le gustó Bill, así que giró y se fue por el otro lado.

En este caso, ser más específico hizo que la oración fuera más clara. Pero eso no siempre va a ser el caso. En algunos casos, ser específico hace que sea más difícil de leer.

A Bill le gustan los libros, entonces Bill fue a la biblioteca y Bill sacó un libro que siempre le gustó a Bill.

En este caso, sería más fácil leer la oración si usáramos "él" y, en algunos casos, omitimos su nombre, esto equivale a usar la palabra clave var .

A Bill le gustan los libros, así que fue a la biblioteca y sacó un libro que siempre le gustó.

Esas analogías cubren la esencia, pero no cuentan toda la historia. Ver en esos ejemplos solo había una forma de referirse a la persona. Ya sea con su nombre, por ejemplo, Bill, o de una manera más general, como "él" y "él". Pero solo estamos trabajando con una palabra.

En el caso del código, tiene dos "palabras", el tipo y el nombre de la variable.

Person p = GetPerson();

La pregunta ahora es si hay suficiente información para que pueda determinar fácilmente qué es p . ¿Todavía sabrías qué es la gente en este escenario?

var p = GetPerson();

Que tal este:

var p = Get();

Que tal este:

var person = Get();

O este:

var t = GetPerson();

O este:

var u = Person.Get();

Si la palabra clave var funciona en un escenario dado depende mucho del contexto del código, como cuáles son los nombres de las variables, clases y métodos, así como también la complejidad del código.

Personalmente, me gusta usar la palabra clave var que sea más completa para . Pero también tiendo a nombrar mis variables después del tipo, así que realmente no estoy perdiendo ninguna información.

Dicho esto, a veces hago excepciones, tal es la naturaleza de cualquier cosa compleja, y el software no es nada si no complicado.


Puede considerar que la opinión de Microsoft es relevante, ya que C # es su lenguaje:

"Sin embargo, el uso de var tiene al menos el potencial de hacer que su código sea más difícil de entender para otros desarrolladores. Por esa razón, la documentación de C # generalmente usa var solo cuando es necesario".

Ver MSDN - Variables locales implícitamente tipadas (Guía de programación C #) , último párrafo.

También debe tener en cuenta que var elimina la prueba de tipo de datos en tiempo de compilación en la asignación inicial.

var x = "mistake"; // error not found by compiler int x = "mistake"; // error found

Como la mayoría de las variables solo se asignan una vez, el uso constante de var elimina casi todas las pruebas de tipo de datos en las asignaciones de variables.

Esto hace que su código sea vulnerable a cambios accidentales, por ejemplo, aquellos hechos por herramientas de fusión o desarrolladores cansados.


Del Departamento de Redundancia del Departamento de Declaración (de Jeff''s Coding Horror ):

"Utilizo el tipado de variables implícito cuando y donde sea que haga que mi código sea más conciso. Todo lo que elimine la redundancia de nuestro código debe ser perseguido agresivamente, hasta e incluyendo el cambio de idiomas".

Yo mismo creo que vale la pena, pero la creación de una guía exhaustiva sobre cuándo usar o no sería exagerado .