Pergunta

Eu tenho uma variante do por questão ref. Eu sei tudo sobre a chamada com o árbitro ou os nossos parâmetros e como isso afeta as variáveis ??e seus valores. Eu tive esse problema com um DataTable e eu quero saber por que uma tabela de dados é diferente de uma variável inteira simples.

Eu tenho a resposta física sobre como corrigir o problema, mas eu quero saber por que ela funciona da maneira que faz.

Se você usar variáveis ??simples que faz o que eu esperava

        int mVar1 = 1;
        int mVar2 =1;

        mVar2 = mVar1;

        mVar2 = 5;

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

exibe 1,5 no console.

Mas se você fizer a mesma coisa com um DataTable faz uma referência à primeira tabela de dados em vez de um novo valor:

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

        }

Os ecrãs da consola: StringCol StringCol123 Teste Teste

dizendo mVar4 = mVar3 que provoca mVar4 para ser uma referência para mVar3.

A solução para este problema é para dizer

DataTable mVar4 = mVar3.Copy(); 

Então, minha pergunta é: o que faz com que uma tabela de dados para executar de forma diferente do que um campo inteiro simples. Por que criar uma referência quando eu uso mVar4 = mVar3 em vez de uma cópia diferente do DataTable?

Foi útil?

Solução

Você está correndo contra a diferença entre um tipo de referência e um tipo de valor.

Aqui está um MSDN artigo sobre as diferenças .

Uma resposta mais descritiva seria a de que ambas são realmente realizar a mesma operação, a diferença é que no primeiro exemplo (os dois inteiros) a atribuição de mVar2 = mvar1 está atribuindo o valor de mvar1 para mVar2, que é um. no entanto, no caso do DataTable, o que está realmente a ser atribuído é um local de memória, não uma DataTable.

Digamos, por exemplo, que o DataTable você criou reside na posição de memória 20. Isso significaria que a referência mvar1 iria realizar uma referência para esse local (20). Quando você faz a atribuição mVar2 = mvar1, você está dizendo mVar2 para manter o mesmo valor que mvar1, então mVar2 então referências ao local de memória 20 também. O resultado é que ambas as variáveis ??referência a mesma DataTable.

A fim de alcançar o comportamento que você está descrevendo, você seria realmente precisa ter uma capacidade de cópia, como você disse. Ele teria que alocar um objeto inteiramente novo e copie o estado do objeto anterior para o novo.

Para a classe DataTable que você poderia estendê-lo como este dentro de um método de extensão:

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

Outras dicas

A chamada mVar2 = mvar1; copia o valor armazenado no local do mvar1. Neste cenário, o que significa 1 é copiado na localização mVar2. Na segunda situação, o valor armazenado a mVar3 é novamente copiados para o local de mVar4. No entanto, neste caso, porque um DataTable é um tipo de referência, o valor que é copiado, é a referência para o objeto DataTable real.

Para mostrar isso ainda mais, adicione o seguinte ao final do código que você postou:

        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

        }

Aqui, se você definir mVar4 para uma nova instância de um DataTable novamente, em seguida, as alterações feitas não se reflecte no mVar3. Isso ocorre porque a chamada mVar4 = new DataTable (); muda a referência no local do mVar4, isso não muda o objeto referenciado por mVar4.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top