Question

C # 3.0 a introduit le mot-clé var. Et lors de la compilation, le compilateur insère les bons types pour vous. Cela signifie qu'il va même travailler sur un moteur d'exécution 2.0. Jusqu'ici tout va bien. Mais l'autre jour, je trouvai un cas où, le mot-clé var serait remplacé par objet juste et donc pas assez précis. Disons que vous avez quelque chose comme:

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
}

Lorsque je tente d'utiliser la ligne à la fois IntelliSense et le compilateur me dit qu'il est objet de type. data.Rows est de type System.Data.DataRowCollection. Les travaux suivants:

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
}

Ce n'est pas une question sur l'utilisation du var, il y a un fil pour que .

J'utilise Visual Studio 2008 SP1 btw.

Edit:. Code correct maintenant attaché

Était-ce utile?

La solution

Je pense que je vois le problème. DataRowCollection est non générique et donc la seule chose que connaît le compilateur est qui contient des objets de type objet. Si cela avait été un générique qui occasionnerait structure de données ont travaillé.

Autres conseils

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

fonctionne comme prévu, il me donne montrant IntelliSense à la fois Bleh et Blah, dans Visual Studio 2008.

Avez-vous quelque chose comme qui, ou exactement qui? Il pourrait y avoir d'autres choses qui Remontée IntelliSense que le code que vous montriez.

Pour répondre à la question réelle. La seule différence entre épelant le type et l'utilisation var, est que, dans certains cas, vous doit utiliser var, lorsque vous n'avez tout simplement pas le type correct pour elle. Ce, si je ne me trompe pas, est pertinent que lorsque vous utilisez des types anonymes.

Il n'y a pas d'autre différence, et le compilateur choisir le même type sur le côté gauche comme il l'a sur le côté droit.

Modifier : Merci @Telos de remarquer que seule différence est que lorsque vous utilisez var, vous devez bien sûr donner la variable une valeur au moment de la déclaration, puisque le type de l'expression sur la droite permet de dicter le type de la variable sur le côté gauche. Lorsque épelant le type, vous pouvez d'opter bien sûr de ne pas lui donner une valeur.

Je pense que somethingThatReturnsY est en fait a déclaré pour revenir X - même si elle retourne Y dans la pratique. Je pense que si vous déclarez y comme Y y = somethingThatReturnsY(); il ne parviendra pas à compiler.

Les règles de var sont assez simples (pour les cas où il travaille -. Il y a plusieurs restrictions pour vous arrêter de faire var x = null; etc

Si vous pensez var est vraiment en train de faire la mauvaise chose, s'il vous plaît poster un programme court mais complet pour démontrer.

J'ai essayé de reproduire ce avec le code suivant dans une application 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() { }
}

Cela fonctionne comme prévu, IntelliSense est correct, et réflecteur montre que j est de type y. Je pense que si votre expérience quelque chose de louche il est plus complexe que le simple cas ici.

J'utilise Visual Studio 2008 RTM ainsi.

DataTable.Rows renvoie une DataRowCollection qui implémente InternalDataCollectionBase, qui à son tour met en œuvre ICollection et IEnumerable. Le code

foreach(DataRow row in dt.Rows) { }

jette chaque élément dans la DataRowCollection à un DataRow. Vous pouvez démontrer cela en changeant à

foreach(int row in dt.Rows) { }

qui compile mais jette un InvalidCastException.

Si DataRowCollection mis en œuvre IEnumerable<DataRow> alors ce ne serait pas compiler et utiliser var taperait chaque objet dans la liste comme DataRow.

Je ne crois pas que vous avez fourni suffisamment d'informations dans votre exemple de code. J'ai fait un petit programme pour essayer d'imiter le comportement que vous décrivez:

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

Mais la sortie montre clairement que var résout le type Y, X pas.

Êtes-vous sûr que votre fonction retourne un Y comme référence Y, et non comme une référence X?

Il fonctionne comme il se doit. Il met le type d'objet comme « objet » lorsque le compilateur est incapable de déterminer le type de données correct.

Lorsque vous utilisez le mot-clé foreach, l'DateRowCollection est accessible si l'interface IEnumerable. La méthode utilisée pour accéder au DataRow est appelé courant et retourne un objet. Ainsi, le mot-clé var est à la recherche à la valeur de retour de la méthode actuelle de déduire le type.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top