Pergunta

C # 3.0 introduziu a palavra-chave var. E quando compilado, o compilador irá inserir os tipos certos para você. Isso significa que ele vai mesmo trabalhar em um tempo de execução 2.0. Por enquanto, tudo bem. Mas no outro dia eu encontrei um caso em que, a palavra-chave var seria substituído com apenas objeto e, portanto, não é suficiente específica. Digamos que você tenha 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
}

Quando tento fileira uso tanto IntelliSense eo compilador me diz que é de tipo de objecto. data.Rows é do tipo System.Data.DataRowCollection. As seguintes 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
}

Esta não é uma pergunta sobre o uso de var, há um fio para que aqui .

Estou usando o Visual Studio 2008 SP1 btw.

Edit:. Código correto agora anexado

Foi útil?

Solução

Eu acho que ver o problema. DataRowCollection é não-genérico e, portanto, a única coisa que o compilador sabe é que contém objetos do tipo de objeto. Se tivesse sido uma estrutura de dados genérica este teria funcionado.

Outras dicas

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 esperado, dá-me intellisense mostrando tanto Bleh e Blah, no Visual Studio 2008.

Você tem algo como que, ou exatamente isso? Pode haver outras coisas que viagem até intellisense do que o código que você mostrou.

Para responder à pergunta real. A única diferença entre soletrando o tipo, e usando var, é que em alguns casos você deve uso var, quando você simplesmente não têm o tipo correto para ele. Isto, se não me engano, só é relevante quando você está usando tipos anônimos.

Não há outra diferença, eo compilador vai pegar o mesmo tipo no lado esquerdo, pois tem no lado direito.

Editar : Graças a @Telos por apontar que uma diferença é que ao usar var, você deve, naturalmente, dar a variável um valor em tempo de declaração, uma vez que o tipo da expressão no lado da mão direita é usada para ditar o tipo da variável no lado da mão esquerda. Quando soletrando o tipo, você pode, naturalmente, optam por não dar-lhe um valor.

Meu palpite é que somethingThatReturnsY é realmente declarou para voltar X - mesmo que retorna Y na prática. Espero que se você declarar y como Y y = somethingThatReturnsY(); ele vai deixar de compilar.

As regras para var são bastante simples (para os casos em que trabalha -. Existem várias restrições para impedi-lo fazendo var x = null; etc

Se você acha var realmente está fazendo a coisa errada, por favor postar um curto, mas completo programa para demonstrar.

Eu tentei reproduzir isso com o seguinte código em um aplicativo de console.

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() { }
}

Isso funciona como esperado, IntelliSense está correto e refletor mostra que j é de digite y. Meu palpite é que se o seu experimentando algo suspeito é mais complexa, então o caso simples aqui.

Estou usando o Visual Studio 2008 RTM também.

DataTable.Rows retornos uma DataRowCollection que implementa InternalDataCollectionBase, que por sua vez implementa ICollection e IEnumerable. O código

foreach(DataRow row in dt.Rows) { }

lança cada item na DataRowCollection a um DataRow. Você pode demonstrar isso alterando-o para

foreach(int row in dt.Rows) { }

que compila mas lança um InvalidCastException.

Se DataRowCollection implementado IEnumerable<DataRow>, então, que não compilar e usando var deve digitar cada objeto na lista como um DataRow.

Eu não acredito que você forneceu informação suficiente em seu código de amostra. Eu fiz um pequeno programa para tentar imitar o comportamento que você descreve:

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";
}

mas a saída mostra claramente que var é resolver o tipo Y, X não.

Você tem certeza que sua função retorna um Y como referência Y, e não como uma referência X?

Ele funciona como deveria. Ela coloca o tipo de objeto como "objeto" quando o compilador é incapaz de determinar o tipo de dados correto.

Quando você usa a palavra-chave foreach, o DateRowCollection é acessado embora a interface IEnumerable. O método específico usado para acessar o DataRow é chamada atual e retorna um objeto. Assim, o var palavra-chave é olhar para o valor de retorno do método atual para inferir o tipo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top