Domanda

Ho una variante alla domanda di ref. So tutto sulla chiamata con ref o i nostri parametri e come influenza le variabili e i loro valori. Ho avuto questo problema con una DataTable e voglio sapere perché un datatable è diverso da una semplice variabile intera.

Ho la risposta fisica su come risolvere il problema, ma voglio sapere perché funziona così.

Se usi variabili semplici, fa quello che mi aspettavo

        int mVar1 = 1;
        int mVar2 =1;

        mVar2 = mVar1;

        mVar2 = 5;

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

viene visualizzato 1,5 nella console.

MA se si fa la stessa cosa con una DataTable si fa riferimento al primo datatable anziché a un nuovo valore:

        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 visualizza: STRINGCOL StringCol123 Test Prova

dicendo mVar4 = mVar3 fa sì che mVar4 sia un riferimento a mVar3.

La soluzione a questo problema è dire

DataTable mVar4 = mVar3.Copy(); 

Quindi la mia domanda è: cosa fa sì che un datatable funzioni diversamente da un semplice campo intero. Perché crea un riferimento quando utilizzo mVar4 = mVar3 anziché una copia diversa della DataTable?

È stato utile?

Soluzione

Stai scontando la differenza tra un tipo di riferimento e un tipo di valore.

Ecco un articolo msdn sulle differenze .

Una risposta più descrittiva sarebbe che entrambi stanno effettivamente eseguendo la stessa operazione, la differenza è che nel primo esempio (i due numeri interi) l'assegnazione di mVar2 = mVar1 assegna il valore di mVar1 a mVar2, che è 1. Tuttavia, nel caso della DataTable, ciò che viene effettivamente assegnato è una posizione di memoria, non una DataTable.

Dire, ad esempio, che la DataTable creata risiede nella posizione di memoria 20. Ciò significherebbe che il riferimento mVar1 conterrebbe un riferimento a quella posizione (20). Quando esegui l'assegnazione mVar2 = mVar1, stai dicendo a mVar2 di mantenere lo stesso valore di mVar1, quindi mVar2 fa riferimento anche alla posizione di memoria 20. Il risultato è che entrambe le variabili fanno riferimento alla stessa DataTable.

Per ottenere il comportamento che stai descrivendo, dovresti davvero avere un'abilità Copia, come hai affermato. Dovrebbe allocare un oggetto completamente nuovo e copiare lo stato dell'oggetto precedente in quello nuovo.

Per la classe DataTable è possibile estenderla in questo modo all'interno di un metodo di estensione:

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

Altri suggerimenti

La chiamata mVar2 = mVar1; copia il valore memorizzato nella posizione di mVar1. In questo scenario, ciò significa che 1 viene copiato nella posizione mVar2. Nella seconda situazione, il valore memorizzato in mVar3 viene nuovamente copiato nella posizione di mVar4. Tuttavia, in questo caso, poiché una DataTable è un tipo di riferimento, il valore che viene copiato è il riferimento all'oggetto DataTable effettivo.

Per dimostrarlo ulteriormente, aggiungi quanto segue alla fine del codice che hai pubblicato:

        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

        }

Qui se imposti di nuovo mVar4 su una nuova istanza di una DataTable, le modifiche apportate non si rifletteranno in mVar3. Questo perché la chiamata mVar4 = new DataTable (); cambia il riferimento nella posizione di mVar4, non cambia l'oggetto a cui fa riferimento mVar4.

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