Domanda

C # 3.0 ha introdotto la parola chiave var. E quando viene compilato, il compilatore inserirà i tipi giusti per voi. Ciò significa che sarà anche il lavoro su un runtime 2.0. Fin qui tutto bene. Ma l'altro giorno ho trovato un caso in cui, la parola chiave var sarebbe sostituito con un oggetto e quindi non abbastanza specifico. Diciamo che avete qualcosa di simile:

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 provo ad usare fila sia IntelliSense e il compilatore mi dice che si tratta di tipo di oggetto. data.Rows è di tipo System.Data.DataRowCollection. Le seguenti opere:

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
}

Questa non è una domanda circa l'uso di var, c'è un filo per quella qui .

Sto usando Visual Studio 2008 SP1 btw.

Modifica:. Corretto codice ora attaccato

È stato utile?

Soluzione

Mi sembra di vedere il problema. DataRowCollection non è generica e quindi l'unica cosa che il compilatore sa è che contiene oggetti di tipo Object. Se fosse stato un datastructure generica questo avrebbe funzionato.

Altri suggerimenti

Questa:

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

funziona come previsto, mi dà intellisense mostra sia Bleh e bla, in Visual Studio 2008.

Hai fatto qualcosa di come che, o esattamente che? Ci potrebbero essere altre cose che viaggio fino intellisense rispetto al codice che avete mostrato.

Per rispondere alla domanda effettiva. L'unica differenza tra precisando il tipo, e l'utilizzo di var, è che in alcuni casi è deve uso var, quando semplicemente non hanno il tipo corretto per esso. Questo, se non mi sbaglio, è rilevante solo quando si utilizza tipi anonimi.

Non c'è altra differenza, e il compilatore vi verrà a prendere lo stesso tipo sul lato sinistro in quanto ha sul lato destro della strada.

Modifica : Grazie a @Telos per aver ricordato che una differenza è che quando si usa var, si deve naturalmente dare alla variabile un valore al momento della dichiarazione, dal momento che il tipo di espressione sul lato destro viene utilizzato per dettare il tipo di variabile sul lato sinistro. Quando precisando il tipo, si può ovviamente scelgono di non dare un valore.

La mia ipotesi è che è in realtà somethingThatReturnsY ha dichiarato per tornare X - anche se restituisce Y nella pratica. Mi aspetto che se si dichiara y come Y y = somethingThatReturnsY(); non riuscirà a compilare.

Le regole per var sono abbastanza semplici (per i casi in cui opera -. Ci sono varie restrizioni per fermare stai facendo var x = null; etc

Se si pensa var realmente sta facendo la cosa sbagliata, si prega di inviare un programma breve ma completo per dimostrare.

Ho cercato di riprodurre questo con il seguente codice in un'applicazione 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() { }
}

Questo funziona come previsto, IntelliSense è corretto, e Riflettore mostra che j è di digitare y. La mia ipotesi è che se il vostro sperimentare qualcosa di sospetto è più complessa allora il caso semplice qui.

Sto usando Visual Studio 2008 RTM pure.

DataTable.Rows restituisce un DataRowCollection che implementa InternalDataCollectionBase, che a sua volta implementa ICollection e IEnumerable. Il codice

foreach(DataRow row in dt.Rows) { }

getta ogni elemento DataRowCollection ad un DataRow. È possibile dimostrare questo cambiando a

foreach(int row in dt.Rows) { }

che compila, ma genera un InvalidCastException.

Se DataRowCollection implementato IEnumerable<DataRow> poi che non sarebbe compilare e utilizzando var sarebbe digitare ogni oggetto nella lista come un DataRow.

Non credo che ci hai fornito abbastanza informazioni nel codice di esempio. Ho fatto un piccolo programma per cercare di emulare il comportamento descritto:

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

Ma l'output mostra chiaramente che var sta risolvendo il tipo Y, X non.

Sei sicuro che la funzione restituisce un Y come riferimento Y, e non come un riferimento X?

E 'funziona come dovrebbe. Si mette il tipo di oggetto come "oggetto" quando il compilatore non è in grado di determinare il tipo di dati corretto.

Quando si utilizza la parola chiave foreach, il DateRowCollection si accede se l'interfaccia IEnumerable. Il metodo specifico utilizzato per accedere al DataRow è chiamata corrente e restituisce un oggetto. Così la parola chiave var sta esaminando il valore di ritorno del metodo corrente per dedurre il tipo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top