使用引用类型的数组赋值?

cmd*_*mpt 0 c# arrays ado.net

假设我有一些已知的库来从.xls文件加载数据,并返回一个DataTable,其中填充了来自任何excel工作簿中第一个工作表的数据.还有一个Log函数,可以在没有工作调试器的情况下打印出消息.

DataTable dtFoo = null;
DataTable dtBar = null;
DataTable dtChaz = null;

String[] files = new String[]{ "file1.xls", "file2.xls", "file2.xls" };
DataTable[] dts = new DataTable[] { dtFoo, dtBar, dtChaz };

for(int i = 0; i < 3; i++)
{
    dts[i] = SomeLibrary.LoadFromFile(files[i]); //Returns a new DataTable
    Log((dts[i] == null) + " " + dts[i].Rows.Count)
}

Log((dts[0] == null) + " " + (dtFoo == null));
Log((dts[1] == null) + " " + (dtBar == null));
Log((dts[2] == null) + " " + (dtChaz == null));
Run Code Online (Sandbox Code Playgroud)

Log Output:

  False 40
  False 455
  False 34
  False True
  False True
  False True
Run Code Online (Sandbox Code Playgroud)

很明显,在使用我无法弄清楚的引用类型变量时,我遗漏了一些重要的东西.循环完成后,为什么我的DataTable变量仍然为null?

Jon*_*eet 7

这一行:

DataTable[] dts = new DataTable[] { dtFoo, dtBar, dtChaz };
Run Code Online (Sandbox Code Playgroud)

...不会使用数组元素对变量进行别名,就像您认为的那样.它只是创建新的数组,并设置初始到的值dtFoo,dtBardtChaz分别(所有这些都是零).之后,数组和变量完全分开.

如果您想稍后设置变量,则需要:

dtFoo = dts[0];
dtBar = dts[1];
dtChaz = dts[2];
Run Code Online (Sandbox Code Playgroud)

当然这不一定是DataTables.简单的例子:

string x = "initial";
string[] array = new string[] { x };
array[0] = "modified";

Console.WriteLine(x); // "initial"
x = array[0];
Console.WriteLine(x); // "modified"
Run Code Online (Sandbox Code Playgroud)

请注意,这是您更改数组元素值时.相反,如果您修改值引用的对象,那就是另一回事:

StringBuilder builder = new StringBuilder("123");
StringBuilder[] array = new StringBuilder[] { builder };
builder[0].Append("456");
Console.WriteLine(builder); // 123456
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅有关引用类型和值类型的文章.基本上,您需要区分引用和它们引用的对象.