Question

J'ai une variante sur la question de renvoi. Je sais tout sur appeler avec le ref ou nos paramètres et comment cela affecte les variables et leurs valeurs. J'ai eu ce problème avec un DataTable et je veux savoir pourquoi un datatable est différent d'une simple variable entière.

J'ai la réponse physique sur la façon de résoudre le problème, mais je veux savoir pourquoi cela fonctionne de la même façon.

Si vous utilisez des variables simples, cela correspond à ce à quoi je m'attendais

        int mVar1 = 1;
        int mVar2 =1;

        mVar2 = mVar1;

        mVar2 = 5;

        Console.WriteLine(mVar1.ToString());
        Console.WriteLine(mVar2.ToString());

il affiche 1,5 dans la console.

MAIS si vous faites la même chose avec un DataTable, il fait référence au premier datatable au lieu d’une nouvelle valeur:

        DataTable mVar3 = new DataTable();
        DataTable mVar4 = new DataTable();


         // Create DataColumn objects of data types.
        DataColumn colString = new DataColumn("StringCol");
        colString.DataType = System.Type.GetType("System.String");
        mVar3.Columns.Add(colString);

        // Create DataColumn objects of data types.
        DataColumn colString2 = new DataColumn("StringCol123");
        colString2.DataType = System.Type.GetType("System.String");
        mVar4.Columns.Add(colString2);

        foreach (DataColumn tCol in mVar3.Columns)
        {
            Console.WriteLine(tCol.ColumnName);

        }
        foreach (DataColumn tCol in mVar4.Columns)
        {
            Console.WriteLine(tCol.ColumnName);

        }

                mVar4 = mVar3;

        //change mVar4 somehow and see if mVar3 changes


        foreach (DataColumn tCol in mVar4.Columns)
        {
            tCol.ColumnName = "Test";

        }

        foreach (DataColumn tCol in mVar3.Columns)
        {
            Console.WriteLine(tCol.ColumnName);

        }

        foreach (DataColumn tCol in mVar4.Columns)
        {
            Console.WriteLine(tCol.ColumnName);

        }

La console affiche: StringCol StringCol123 Tester Test

en disant mVar4 = mVar3, il fait en sorte que mVar4 soit une référence à mVar3.

La solution à ce problème consiste à dire

DataTable mVar4 = mVar3.Copy(); 

Donc, ma question est: Qu'est-ce qui fait qu'un datatable fonctionne différemment d'un simple champ entier? Pourquoi crée-t-il une référence lorsque j'utilise mVar4 = mVar3 au lieu d'une copie différente de DataTable?

Était-ce utile?

La solution

Vous vous heurtez à la différence entre un type de référence et un type de valeur.

Voici un article msdn sur les différences .

Une réponse plus descriptive serait que les deux exécutent la même opération. La différence est que, dans le premier exemple (les deux entiers), l’affectation de mVar2 = mVar1 attribue la valeur de mVar1 à mVar2, qui est 1. Toutefois, dans le cas du DataTable, ce qui est réellement attribué est un emplacement de mémoire, pas un DataTable.

Disons, par exemple, que le DataTable que vous avez créé réside dans l'emplacement de mémoire 20. Cela voudrait dire que la référence mVar1 contiendrait une référence à cet emplacement (20). Lorsque vous effectuez l'affectation mVar2 = mVar1, vous indiquez à mVar2 de conserver la même valeur que mVar1. Par conséquent, mVar2 fait également référence à l'emplacement de mémoire 20. Le résultat étant que les deux variables font référence au même DataTable.

Pour obtenir le comportement que vous décrivez, il vous faudrait en effet une capacité de copie, comme vous l'avez indiqué. Il devrait allouer un objet entièrement nouveau et copier l'état de l'objet précédent dans le nouvel objet.

Pour la classe DataTable, vous pouvez l'étendre de la manière suivante dans une méthode d'extension:

public static DataTable Copy(this DatTable original)
{
   var result = new DataTable();
   //assume Property1 was a property of a DataTable
   result.Property1 = original.Property1; 
   //continue copying state from original to result
   return result;
}

Autres conseils

L'appel mVar2 = mVar1; copie la valeur stockée à l’emplacement de mVar1. Dans ce scénario, cela signifie que 1 est copié à l'emplacement mVar2. Dans le second cas, la valeur stockée dans mVar3 est à nouveau copiée à l'emplacement de mVar4. Cependant, dans ce cas, comme DataTable est un type de référence, la valeur copiée correspond à la référence à l’objet DataTable réel.

Pour afficher ceci davantage, ajoutez ce qui suit à la fin du code que vous avez posté:

        mVar4 = new DataTable();
        // Create DataColumn objects of data types.
        DataColumn colString3 = new DataColumn("StringCol1234");
        colString2.DataType = System.Type.GetType("System.String");
        mVar4.Columns.Add(colString3);

        foreach (DataColumn tCol in mVar3.Columns)
        {
            Console.WriteLine(tCol.ColumnName); // still outputs test

        }

        foreach (DataColumn tCol in mVar4.Columns)
        {
            Console.WriteLine(tCol.ColumnName); // now outputs StringCol1234

        }

Ici, si vous définissez à nouveau mVar4 sur une nouvelle instance d’un DataTable, les modifications apportées ne sont pas reflétées dans mVar3. En effet, l'appel mVar4 = new DataTable (); change la référence à l'emplacement de mVar4, il ne change pas l'objet référencé par mVar4.

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