diferente por questão ref usando um simples =
-
06-07-2019 - |
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?
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.