0

假设我有一些已知的库来从 .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));

Log Output:

  False 40
  False 455
  False 34
  False True
  False True
  False True

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

4

3 回答 3

7

这一行:

DataTable[] dts = new DataTable[] { dtFoo, dtBar, dtChaz };

... 不会像您认为的那样将变量与数组元素混为一谈它只是创建一个新数组,并将初始dtFoo分别设置为,dtBar和的值dtChaz(所有这些都为空)。之后数组和变量完全分开。

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

dtFoo = dts[0];
dtBar = dts[1];
dtChaz = dts[2];

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

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

Console.WriteLine(x); // "initial"
x = array[0];
Console.WriteLine(x); // "modified"

请注意,这是当您更改数组元素的值时。相反,如果您修改该值所指的对象,那就是另一回事了:

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

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

于 2013-01-15T19:28:57.727 回答
2

作为建议,您可以代替您尝试过的代码

DataSet ds = new DataSet();
ds.Tables.Add(dtFoo);
ds.Tables.Add(dtBar);
ds.Tables.Add(dtChaz );

将表添加到数据集而不是创建数据表数组

所以修改后的代码将是

DataSet ds = new DataSet();
for(int i = 0; i < 3; i++)
{
    ds.Tables.Add(SomeLibrary.LoadFromFile(files[i])); //Returns a new DataTable
}
于 2013-01-15T19:30:22.680 回答
1

您需要添加行

dtFoo = dts[0];
dtBar = dts[1];
dtChaz = dts[2];

在日志行之前。

init 语句对赋值语句没有影响。

于 2013-01-15T19:32:37.000 回答