Frage

C 3.0 # das var Schlüsselwort eingeführt. Und wenn kompiliert, wird der Compiler die richtigen Typen für Sie einsetzen. Dies bedeutet, dass es auch auf einer 2.0-Laufzeit arbeiten. So weit, ist es gut. Aber neulich habe ich einen Fall, wo würde das var Schlüsselwort mit nur Objekt ersetzt werden und somit nicht spezifisch genug. Angenommen, Sie haben so etwas wie:

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
}

Wenn ich versuche, Zeile zu verwenden beide IntelliSense und der Compiler sagt mir, dass es von Typ-Objekt. data.Rows ist vom Typ System.Data.DataRowCollection. Die folgenden Werke:

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
}

Dies ist keine Frage über die Verwendung von var gibt es einen Thread für die hier .

Ich bin mit Visual Studio 2008 SP1 btw.

Edit:. Richtige Code jetzt angebracht

War es hilfreich?

Lösung

Ich denke, dass ich das Problem zu sehen. DataRowCollection ist nicht generisch und damit das einzige, was der Compiler weiß, ist, dass Objekte vom Typ Object enthält. Wenn es sich um eine generische Datenstruktur gewesen wäre dies gearbeitet haben.

Andere Tipps

Dieses:

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

funktioniert wie erwartet, es gibt mir intellisense sowohl Bleh und Blah, in Visual Studio 2008 zeigt.

Haben Sie etwas wie das, oder genau das? Es könnten auch andere Dinge, die den Code stolpern intellisense als Sie zeigte.

die eigentliche Frage zu beantworten. Der einzige Unterschied zwischen den Typ Rechtschreibung und var verwenden, ist, dass in einigen Fällen Sie muss verwenden var, wenn man einfach nicht den richtigen Typ für sie tun. Dies, wenn ich mich nicht irre, ist nur dann relevant, wenn Sie anonyme Typen verwenden.

Es gibt keinen anderen Unterschied, und der Compiler den gleichen Typen auf der linken Seite wählen, wie es auf der rechten Seite hat.

Bearbeiten : Dank @Telos für den Hinweis auf, dass ein Unterschied, dass bei Verwendung von var, müssen Sie natürlich geben die Variable einen Wert bei der Deklaration, da die Art des Ausdrucks auf der rechten Seite verwendet wird, um den Typ der variablen auf der linken Seite zu diktieren. Wenn die Art formulierend, können Sie natürlich opt kann es keinen Wert geben.

Meine Vermutung ist, dass somethingThatReturnsY ist eigentlich erklärt X zurückzukehren - auch wenn es zurückkehrt Y in der Praxis. Ich gehe davon aus, dass, wenn Sie y als Y y = somethingThatReturnsY(); erklären wird es nicht kompilieren.

Die Regeln für var ziemlich einfach sind (für die Fälle, in denen es funktioniert -. Gibt es verschiedene Einschränkungen, Sie zu stoppen tun var x = null; etc

Wenn Sie denken, var wirklich die falsche Sache tun, schreiben Sie bitte ein kurzes, aber vollständige Programm zu zeigen.

Ich habe versucht, dies in einer Konsolenanwendung mit dem folgenden Code zu reproduzieren.

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

Dies funktioniert wie erwartet, ist IntelliSense richtig und Reflector zeigt, dass j ist von Typ y. Meine Vermutung ist, dass, wenn Ihr etwas erleben fischig es komplizierter ist dann der einfache Fall hier.

Ich bin mit Visual Studio 2008 RTM als auch.

DataTable.Rows gibt eine DataRowCollection die InternalDataCollectionBase implementiert, die wiederum implementiert ICollection und IEnumerable. Der Code

foreach(DataRow row in dt.Rows) { }

wirft jedes Element in der DataRowCollection zu einem DataRow. Sie können dies zeigen, indem sie auf

Ändern
foreach(int row in dt.Rows) { }

, die kompiliert aber eine InvalidCastException.

Wenn DataRowCollection IEnumerable<DataRow> implementiert dann das würde nicht kompilieren und var würde jedes Objekt in der Liste als DataRow geben.

Ich glaube nicht, dass Sie genügend Informationen in Ihrem Beispielcode zur Verfügung gestellt haben. Ich habe ein kleines Programm, um zu versuchen, das Verhalten zu emulieren Sie beschreiben:

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

Aber der Ausgang zeigt deutlich, dass var den Y-Typ ist die Lösung, nicht X.

Sind Sie sicher, dass Ihre Funktion eine Y als Y-Referenz zurückgibt, und nicht als X-Referenz?

Es funktioniert, wie es sollte. Es setzt den Objekttyp als „Objekt“, wenn der Compiler nicht in der Lage ist, den richtigen Datentyp zu bestimmen.

Wenn Sie die foreach Schlüsselwort verwenden, wird die DateRowCollection obwohl die IEnumerable-Schnittstelle zugegriffen. Die spezifische Methode verwendet, um die DataRow Zugriff heißt Strom und gibt ein Objekt zurück. Also das Schlüsselwort var an dem Rückgabewert der aktuellen Methode suchen, um die Art zu schließen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top