Pregunta

C # 3.0 introduce la palabra clave var. Y cuando se compila, el compilador insertará el tipo correcto para usted. Esto significa que se va a trabajar incluso en un tiempo de ejecución 2.0. Hasta aquí todo bien. Pero el otro día me encontré con un caso en el que, la palabra clave var sería reemplazado con un objeto justo y por lo tanto no lo suficientemente específica. Digamos que tiene algo como:

var data = AdoMD.GetData(...); // GetData returns a DataTable

foreach (var row in data.Rows)
{
     string blah = (string)row[0]; // it fails since it's of type object
}

Cuando intento utilizar tanto fila IntelliSense y el compilador me dice que se trata de tipo de objeto. data.Rows es de tipo System.Data.DataRowCollection. Las siguientes obras:

var data = AdoMD.GetData(...); // GetData returns a DataTable

foreach (DataRow row in data.Rows)
{
     string blah = (string)row[0]; // works since it now has the right type
}

Esto no es una pregunta sobre el uso de var, hay un hilo para que aquí .

Estoy usando Visual Studio 2008 SP1 por cierto.

Editar:. Correcta de código que ahora se atribuye

¿Fue útil?

Solución

Creo que veo el problema. DataRowCollection no es genérico y por lo tanto lo único que el compilador sabe es que contiene objetos del tipo de objeto. Si hubiera sido una estructura de datos genérica esto habría funcionado.

Otros consejos

Este:

using System;

namespace Test
{
    public class X
    {
        public String Bleh;
    }

    public class Y : X
    {
        public String Blah;
    }

    public static class Program
    {
        public static void Main()
        {
            var y = SomeFunctionThatReturnsY();
            // y. <-- this gives me both Blah and Bleh in the dropdown
        }

        public static Y SomeFunctionThatReturnsY()
        {
            return new Y();
        }
    }
}

funciona como se espera, me da IntelliSense muestra tanto bleh y bla, en Visual Studio 2008.

¿Ha tenido algo como que, o exactamente que? Puede haber otras cosas que viaje hasta intelisense que el código que mostraste.

Para responder a la pregunta real. La única diferencia entre explicando el tipo, y el uso de var, es que en algunos casos es debe var uso, en las que simplemente no tiene el tipo correcto para él. Esto, si no me equivoco, sólo es relevante cuando se está utilizando tipos anónimos.

No hay ninguna otra diferencia, y el compilador recogerá del mismo tipo en el lado izquierdo, ya que tiene en el lado derecho.

Editar : Gracias a @Telos para señalar que una diferencia es que cuando se usa var, se debe dar por supuesto la variable un valor en el momento de la declaración, ya que el tipo de la expresión en el lado derecho se utiliza para dictar el tipo de la variable en el lado izquierdo. Cuando explicando el tipo, puede, por supuesto opt para no darle un valor.

Mi conjetura es que es en realidad somethingThatReturnsY declarado para regresar X - incluso si se vuelve Y en la práctica. Espero que si se declara como y Y y = somethingThatReturnsY(); se producirá un error al compilar.

Las reglas para var son bastante simples (para los casos en los que trabaja -. Hay varias restricciones que le impida hacer var x = null; etc.

Si cree var realmente está haciendo algo incorrecto, por favor enviar un programa corto pero completo para demostrar.

He intentado reproducir este con el código siguiente en una aplicación de consola.

class Program
{
    static void Main(string[] args)
    {
        var j = returny();
        j.blah();
    }

    private static y returny()
    {
        return new y();
    }
}

class x
{
}

class y : x
{
    public void blah() { }
}

Esto funciona como se esperaba, IntelliSense es correcta, y Reflector muestra que es de j escriba y. Mi conjetura es que si su experimentando algo a pescado es más complejo que el simple caso aquí.

Estoy utilizando Visual Studio 2008 RTM también.

DataTable.Rows devuelve un DataRowCollection que implementa InternalDataCollectionBase, que a su vez implementa ICollection y IEnumerable. El código

foreach(DataRow row in dt.Rows) { }

proyecta cada elemento de la DataRowCollection a un DataRow. Se puede demostrar esto cambiándola a

foreach(int row in dt.Rows) { }

que compila pero lanza una InvalidCastException.

Si DataRowCollection implementado IEnumerable<DataRow> entonces que no habría compilar y usar var sería escribir cada objeto en la lista como un DataRow.

No creo que haya proporcionado suficiente información en su código de ejemplo. Hice un pequeño programa para tratar de emular el comportamiento que describes:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var y = SomeFunctionThatReturnsY();

        MessageBox.Show(y.bla);

        return;
    }

    private Y SomeFunctionThatReturnsY()
    {
        return new Y();
    }
}

internal class X { }

internal class Y : X
{
    public string bla = "Saw a Y, not an X";
}

Pero el resultado muestra claramente que var está resolviendo el tipo Y, no X.

¿Está seguro de que su función devuelve una Y como referencia Y, y no como una referencia X?

funciona como debería. Pone el tipo de objeto como "objeto" cuando el compilador no puede determinar el tipo de datos correcto.

Cuando se utiliza la palabra clave foreach, se accede a la DateRowCollection aunque la interfaz IEnumerable. El método específico utilizado para acceder a la DataRow se llama actual y devuelve un objeto. Así que la palabra clave var está mirando el valor de retorno del método actual para inferir el tipo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top