2008-10-25 9 views
50

esta es una pregunta que al programar siempre me pregunto: ¿Qué hay que usar cuando estamos escribiendo código:Qué usar: ¿tipo de nombre var u objeto?

var myFiles = Directory.GetFiles(fullPath); 

o

string[] myFiles = Directory.GetFiles(fullPath); 

var es nuevo y es un Implícitamente Typed Variables locales, por lo que solo podemos usar localmente y tiene reglas como no puede ser nulo, etc., pero me pregunto si obtendremos alguna ventaja de usarlo "normalmente".

El "normalmente" parte dice, no en tipos anónimos, colección de objetos y Inicializadores y consulta Expresiones, donde esa fue la intención de utilizar el objeto anónimo var, así que lo que quiero decir es que ... sólo como el ejemplo de arriba

¿Cuáles son sus pensamientos?

+2

Gran pregunta. – Contango

Respuesta

59

Más allá del uso evidente de var con LINQ, yo también lo uso para abreviar las declaraciones de variables peludas para facilitar la lectura, por ejemplo:

var d = new Dictionary<string, Dictionary<string, Queue<SomeClass>>>(); 

En general, me sale una especie de comodidad (a falta de una palabra mejor) de mecanografía estática que me hace reacio a renunciar a ella. Me gusta la sensación de que sé lo que estoy haciendo cuando declaro una variable. Declarar una variable no es solo decirle al compilador algo, sino decirle a la persona que lee algo sobre su código.

Déjeme darle un ejemplo. Supongamos que tengo un método que devuelve un List<string>. Este código es ciertamente correcto, y creo que es como el 90% de los desarrolladores de C#, probablemente escribirlo:

List<string> list = MyMethod(); 

Obviamente, ¿verdad? De hecho, aquí hay un lugar donde puedes usar var.

Es cierto. Pero esta versión del código no se acaba de declarar una variable, que me está diciendo lo que la persona que lo escribió tiene la intención de hacer:

IEnumerable<string> list = MyMethod(); 

El desarrollador que escribió el código me está diciendo "Soy no voy a cambiar esta lista, ni voy a usar un índice para acceder a sus miembros. Todo lo que voy a hacer es repetirlo ". Esa es una gran cantidad de información para transmitir en una sola línea de código. Es algo a lo que renunciar si usa var.

Por supuesto, no lo va a dejar si no lo estaba usando en primer lugar. Si usted es el tipo de desarrollador que escribiría esa línea de código, ya sabe que no usaría var allí.

Editar:

Me acabo de releer el post de Jon Skeet, y esta cita de Eric Lippert me llamó la atención:

locales Implícitamente se escriben sólo una pequeña forma en que se puede quitar importancia a la cómo y por lo tanto enfatizar el qué.

Creo que en realidad en muchos casos el uso de tipeo implícito es lo que implícito. Está bien no pensar en el qué. Por ejemplo, voy a escribir casualmente una consulta LINQ como:

var rows = from DataRow r in parentRow.GetChildRows(myRelation) 
      where r.Field<bool>("Flag") 
      orderby r.Field<int>("SortKey") 
      select r; 

Cuando leí ese código, una de las cosas que pienso cuando estoy leyendo es "rows es un IEnumerable<DataRow>."Porque sé que lo que LINQ consulta de retorno es IEnumerable<T>, y puedo ver el tipo del objeto que se ha seleccionado allí mismo.

Eso es un caso en el que lo no ha ha hecho explícito. Se ha dejado para mí .. para inferir

Ahora, en alrededor del 90% de los casos en los que uso de LINQ, esto no importa un poquito porque el 90% de las veces, la siguiente línea de código es:

foreach (DataRow r in rows) 

Pero no es difícil imaginar un código en el que sería muy útil declarar rows como IEnumerable<DataRow> - código donde se consultaban muchos tipos diferentes de objetos, no era factible colocar la declaración de consulta al lado de la iteración, y sería útil poder inspeccionar rows con IntelliSense. Y eso es una cosa, no una cuestión de cómo.

+3

Para el último bit, estoy un poco en desacuerdo. El "qué" no se entiende como "de qué tipo es", sino "para qué sirve". Sé que "var rows" declara una variable que contiene mis filas. ¿Qué más necesito saber? Presumiblemente, se comporta como una colección de filas, por lo que realmente no me importa el tipo exacto. – jalf

+0

Veo en la gran base de código que los desarrolladores de mi compañía usan esto para ahorrar unas pocas teclas y trasladar una carga de comprensión al lector.No tengo ninguna duda de que cualquiera que use esta respuesta puede hacer que el código sea más legible, si dan una maldición y usan el juicio adecuado, pero en el mundo real, los desarrolladores perezosos están teniendo un buen día con esto. – toddmo

+0

Solo quería señalar que no necesita 'abandonar' el tipado estático cuando usa 'var'. Son conceptos mutuamente excluyentes. El agotamiento rápido para futuros visitantes ... ** Escritura estática vs dinámica **: * Static * comprueba en tiempo de compilación, mientras que * Dynamic * comprueba en tiempo de ejecución. ** Tipeo explícito vs implícito **: la declaración de variable * explícita * incluye el tipo explicado, mientras que la declaración de variable * implícita * significa que el compilador infiere el tipo correcto. – KyleMit

41

Obtendrá una gran variedad de opiniones sobre esta, desde "use var everywhere" hasta "use solo var con tipos anónimos, donde básicamente tiene que hacerlo". Me gusta Eric Lippert's take on it:

Todo el código es una abstracción. ¿Qué el código está "realmente" haciendo es manipular datos? No. Números? Bits? No. ¿Voltajes? No. ¿Electrones? Sí, pero entender el código en el nivel de electrones es una mala idea! El arte de la codificación es descubrir cuál es el nivel de abstracción correcto para el público .

En un lenguaje de alto nivel hay siempre esta tensión entre lo que hace el código (semánticamente) y cómo el código la cumple. Los programadores de mantenimiento deben comprender el qué y el cómo si van para tener éxito en la realización de cambios.

El objetivo de LINQ es que quita énfasis de forma masiva al "cómo" y acentúa masivamente el "qué". Por utilizando una comprensión de consulta, el programador está diciendo que el futuro audiencia "Creo que se debe saber ni cuidar exactamente cómo este conjunto de resultados se está calculando, pero debe preocuparse mucho por lo que el semántica del conjunto resultante son ". Hacen que el código esté más cerca del proceso de negocio que se está implementando y más lejos de los bits y electrones que lo hacen ir.

locales Implícitamente se escriben sólo una pequeña forma en que se puede quitar énfasis el cómo y con ello hacen hincapié en la qué. Si eso es lo correcto para hacer en un caso particular es una llamada de juicio .Así que le digo a la gente que si el conocimiento del tipo es relevante y su elección es crucial para el funcionamiento continuo del método , , entonces no utilice tipeo implícito. Mecanografía explícita dice "Te estoy diciendo cómo esto funciona por una razón, paga atención". La tipificación implícita dice " no importa si esta cosa es una lista o un cliente [], lo que importa es que es una colección de clientes".

En lo personal no me tienden a usarlo si el tipo no es razonablemente obvio - donde incluyo consultas LINQ como ser "razonablemente obvio". No lo haría por Directory.GetFiles por ejemplo, ya que no es realmente obvio que devuelve string[] en lugar de (digamos) FileInfo[] (o algo completamente diferente), y eso hace una gran diferencia en lo que haces después.

Si hay una llamada de constructor en el lado derecho del operador de asignación, es mucho más probable que vaya con var: es descaradamente obvio cuál será el tipo. Esto es particularmente útil con tipos genéricos complejos, p. Dictionary<string,List<int>>.

+3

Lo hago muy parecido. Sin embargo, además de la llamada del constructor en el lado derecho, también siempre la uso si se coloca el lado derecho, es decir, hay un "como MyType" al final. – OregonGhost

+3

"Manipulador de electrones" será el título oficial de mi función a partir de ahora: p – dvdvorle

11

Personalmente yo sólo uso var en dos lugares:

  1. Con los tipos anónimos, es decir. relacionados LINQ-(donde se requiere var en algunos casos)
  2. Cuando la instrucción declara y construye un tipo específico al mismo tipo

es decir. este es un ejemplo del punto 2:

var names = new List<String>(); 

Editado: Esto en respuesta a la pregunta de Jon Skeet.

La respuesta anterior fue, de hecho, simplificada. Básicamente, yo uso var donde el tipo es o bien:

  1. innecesario conocer (no es que muchos lugares aunque)
  2. imposible saber (LINQ, tipos anónimos)
  3. Si no conocido, o claros de los el código

en el caso de un método de fábrica, donde todo lo que necesita saber en el lugar donde se escribe el código es que el objeto que se obtiene es un descendiente de algún tipo, y que algún tipo tiene un método de fábrica estático, luego usaría var. De esta manera:

var connection = DatabaseConnection.CreateFromConnectionString("..."); 

El ejemplo anterior es un ejemplo real de mi código. Está claro, al menos para mí y las personas que usan este código, que la conexión es un descendiente de DatabaseConnection, pero el tipo exacto no es necesario ni para entender el código ni para usarlo.

+0

¿Qué pasa con los métodos estáticos de fábrica, p. Foo.CreateInstance (...)? –

+0

¿Puede explicar por qué establece DO: 'var connection = ...' if _ el tipo exacto no es necesario ni para entender el código ni para usarlo._ –

+0

Es solo una guía de estilo. –

9

Probé el estilo "use var everywhere" ... y esta es la razón por la que no continué usándolo.

  1. legibilidad degradado a veces
  2. Límites Intellisense después =
  3. Typing "var" realmente no era mucho más corto que escribir "int", "cadena", etc., especialmente con IntelliSense.

Dicho esto, SÍ todavía lo uso con LINQ.

3

Este post tiene algunas buenas pautas sobre cuándo usar la interfaz tipo var o los tipos de objetos.

1

Creo que es interesante observar cómo esto se maneja generalmente en Haskell. Gracias al Curry-Howard isomorphism, se puede inferir el tipo (más general) de cualquier expresión en Haskell, y, por lo tanto, las declaraciones de tipo no son necesarias en ninguna parte, con algunas excepciones; por ejemplo, a veces deliberadamente desea limitar el tipo a algo más específico de lo que se deduciría.

Por supuesto, lo que se requiere y lo que se recomienda no son lo mismo; en la práctica, la convención parece ser que las definiciones de nivel superior siempre tienen declaraciones de tipo, mientras que las definiciones localizadas tienen las declaraciones de tipo omitidas. Esto parece lograr un buen equilibrio entre la claridad de legibilidad de la definición como un todo, en contraste con la brevedad de legibilidad de las definiciones locales "auxiliares" o "temporales". Si lo entiendo correctamente, no puede usar var para las definiciones de "nivel superior" (como un método o función global) en primer lugar, así que supongo que esto se traduce como "use var donde pueda" en C# world. Por supuesto, escribir "int" es el mismo número de teclas que "var", pero la mayoría de los ejemplos serán más largos que eso.

3

Viniendo de la tierra de la programación funcional, donde la inferencia de tipos rige el día, utilizo var para todos los locales siempre que sea posible.

En Visual Studio, si alguna vez se pregunta cuál es el tipo de cualquier local, todo lo que tiene que hacer es pasar el mouse sobre él con el mouse.

3

Tiendo a utilizar var en todas partes, pero mis compañeros de trabajo dijeron: detente, es menos legible para nosotros. Así que ahora uso var solo en tipos anónimos, consultas LINQ y dónde está el constructor en el lado derecho.

Cuestiones relacionadas