0

Lets say I have some known library to load data from an .xls file and returns a DataTable populated with data from the first sheet in any excel workbook. Also a Log function that prints out messages in the absence of a working debugger.

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

Clearly I'm missing something important when working with reference type variables that I haven't been able to figure out. Why are my DataTable variables still null after the loop completes?

1
  • 2
    Look into using a DataSet. The DataTable array will copy the DataTables into it. Commented Jan 15, 2013 at 19:28

3 Answers 3

7

This line:

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

... doesn't alias the variables with the array elements, as you seem to think it does. It just creates a new array, and sets the initial values to the values of dtFoo, dtBar and dtChaz respectively (all of which are null). The array and the variables are entirely separate afterwards.

If you want to set the variables later, you'll need:

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

Of course this doesn't have to be with DataTables. Simple example:

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

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

Note that this is when you change the value of the array element. If instead you modify the object that the value refers to, that's a different matter:

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

See my article on reference types and value types for more details. Basically you need to differentiate between references and the objects they refer to.

Sign up to request clarification or add additional context in comments.

1 Comment

I think I understand. So lets say I changed my DataTable dtFoo = null; lines to DataTable dtFoo = new DataTable(); & dtBar, dtChaz for all 3 DataTables. And my SomeLibrary.LoadFromFile function added rows to the table instead of returning a new one -- it would work?
2

as suggestion you can do instead of the code you tried

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

addd table to dataset instead of creating array of datatable

so modified code will be

DataSet ds = new DataSet();
for(int i = 0; i < 3; i++)
{
    ds.Tables.Add(SomeLibrary.LoadFromFile(files[i])); //Returns a new DataTable
}

Comments

1

You need to add the lines

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

Before the log lines.

The init statement has no effect on the assignment statements.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.