2012-02-03 12 views
8

Si uno recorre un XmlNodeList como esto¿Por qué var infer type object y no XmlNode en XmlNodeList loop?

foreach (XmlNode foo in xmlNodeList) {string baa = foo.Attributes["baa"].Value;} 

todo funciona como se esperaba - foo es claramente de tipo XmlNode y el IDE de VS.NET muestra los métodos y campos.

Por otro lado

foreach (var foo in xmlNodeList) { string baa = foo.Attributes["baa"].Value; } 

no está compilando porque aquí foo es de tipo objeto. Tipo tipo de inferencia funciona pero infiere objeto.

Al parecer, los elementos de XmlNodeList no son de un solo tipo definido, pero asignándolos a XmlNode en lugar de var hace algo de manera implícita (colada o unboxing).

Primera pregunta: ¿cuál es el mecanismo detrás de eso?

Segunda pregunta (relacionada): ¿cómo encontrar los tipos que se pueden usar en este tipo de bucle? ¿El VS.NET IDE ayuda?

+1

Puede usar las clases en el espacio de nombres system.xml.linq ya que implementan las versiones genéricas IEnumerable entre otras. La var debe inferirse correctamente cuando se usan estas clases. YMMV –

+0

@Chris: Gracias por la pista, lo comprobaré. – Olaf

+0

+1, solo iba a hacer la misma pregunta :-) –

Respuesta

9

XmlNodeList implementa solo la interfaz no genérica IEnumerable, y no algo así como IEnumerable<XmlNode> con genéricos. Esto evita una fuerte tipificación de sus elementos hasta que se realice el moldeado de forma adecuada, por lo que el compilador no tiene más remedio que asignar la declaración de tipo implícita al object en su foreach.

Si usted insiste en el uso de la palabra clave var, puede convertir los elementos de xmlNodeList así:

foreach (var foo in xmlNodeList.Cast<XmlNode>()) 
{ 
    string baa = foo.Attributes["baa"].Value; 
} 

Pero eso es feo, y requiere más pulsaciones de teclado de todos modos. También puede declarar explícitamente XmlNode foo, y dejar que el foreach lo eche sobre la marcha.

+0

Muchas gracias, entendido! No quiero feo, pero como escribí en mi comentario a Jon, la pregunta tenía en parte una parte práctica: si Resharper me da 'var', ¿cuál es la forma más rápida de encontrar el tipo real? – Olaf

+1

Como señala Daniel Hilgarth, la manera más fácil de hacerlo es mirando la documentación. – BoltClock

4

Como notas de BoltClock, XmlNodeList solo implementa IEnumerable.

El bucle foreach automáticamente hace el casting para que detrás de las escenas, así que esto:

List<object> values = new List<object> { "x", "y", "z" }; 
foreach (string x in values) 
{ 
    ... 
} 

es totalmente legal, y realiza una conversión (que puede lanzar una excepción, por supuesto) en cada valor.

No me parece muy claro a qué te refieres con tu segunda pregunta, pero te recomendaría que uses explícitamente XmlNode en tu ciclo. Si realmente desea utilizar var, se podría escribir:

foreach (var foo in xmlNodeList.Cast<XmlNode>()) 

pero que se siente como una exageración para mí ...

+0

Gracias, IEnumerable vs. IEnumerable lo explica! Con mi segunda pregunta quise decir: en un caso como este, ¿cuál es la forma más rápida de encontrar el tipo de elemento que necesito, en este caso 'XmlNode'? Resharper me da 'var', así que me preguntaba si VS.NET lo tiene oculto en algún lugar en su intellisense. – Olaf

+3

@Olaf: No, no puede haber ningún Intellisense en esto, porque la información simplemente no está allí. Necesita saber lo que está haciendo, que de todos modos debería, por supuesto :) –

+0

Eso es lo que quería saber (la información simplemente no está allí). Gracias por ayudarme a saber lo que estoy haciendo! – Olaf

4

XmlNodeList ha sido en el .NET Framework antes de que apoya los genéricos. Por eso, implementa solo la interfaz no genérica IEnumerable y no la genérica IEnumerable<T>.
Para saber qué tipos pueden estar en esta lista, debe leer la documentación. La mejor manera es el indexer.

BTW: El IDE no se ha llamado VS.NET desde que se lanzó Visual Studio 2005 :-) Se llama VS solo desde entonces.

+0

+1 para explicar por qué. No estoy muy familiarizado con las API XML en .NET ... – BoltClock

+0

Gracias, también por la sugerencia de VS.NET (¡aún lo estamos usando internamente!). – Olaf

Cuestiones relacionadas