我有一个C#函数可以翻转DataSet的方向:
static DataSet FlipDataSet(DataSet my_DataSet)
{
using (DataSet ds = new DataSet())
{
foreach (DataTable dt in my_DataSet.Tables)
{
DataTable table = new DataTable();
for (int i = 0; i <= dt.Rows.Count; i++)
{
table.Columns.Add(Convert.ToString(i));
}
DataRow r = null;
for (int k = 0; k < dt.Columns.Count; k++)
{
r = table.NewRow();
r[0] = dt.Columns[k].ToString();
for (int j = 1; j <= dt.Rows.Count; j++)
r[j] = dt.Rows[j - 1][k];
table.Rows.Add(r);
}
ds.Tables.Add(table);
table.Dispose();
}
return ds;
}
}
我从在interwebs上找到的片段修改了此代码,将创建的DataSet包装在using语句中,并显式处理它创建的IDisposable对象。我的问题是,在处理方面,DataSet(上面代码中的“ds”)在返回时会发生什么?我退回之后无法在ds上显式调用.Dispose(),显然,.NET返回值然后正确处理它,或者我完全错过了什么?
答案 0 :(得分:12)
你可能不想这样做。 DataSet
阻止退出using
,无论 块如何退出(正常退出,返回或抛出异常),这意味着您返回的值将是处理并且对呼叫者来说几乎无法使用。
正确的做法是在此函数中没有using
块。 using
块应该在调用者中。
答案 1 :(得分:5)
ds
DataSet
将在您离开using
区块后立即处理,因此您将向调用方返回已处置的DataSet
。
为什么您说在退回后Dispose
无法致电DataSet
?我怀疑这正是你需要做的。
从using
方法中删除FlipDataSet
块,然后在调用代码中处理返回的DataSet
,最好将其包装在using
块中。
答案 2 :(得分:3)
正如另一个答案所述,您将返回已处置的数据集。这是“坏事” TM 。
我非常强烈地相信每个 IDisposable应始终包装在使用块中。但是,有时诀窍正是使用块的地方。对于返回IDisposable的函数,您只需正常创建对象。 using block包含调用函数的行。
答案 3 :(得分:3)
你已经有了一些非常好的答案,但我想展示另一个人。
这实际上是一个所有权问题。谁拥有DataSet
负责处理它。但是,谁真的拥有它?在这种情况下,FlipDataSet
创建新实例,但正在转移所有权,因为它将该实例返回给调用者,并且不会继续保持引用本身。这意味着实例的生命周期管理现在是调用者的责任。
在将这种情况概括为其他情景时,考虑所有权是有益的。仅仅因为属性或方法碰巧返回IDisposable
实例并不意味着它正在转移所有权。理想情况下,您将遵循API的文档提示。但是,在大多数情况下,我看到有一种暗示:如果实例是从属性中提取的,那么该实例仍然由包含类所拥有,在这种情况下,管理生命周期不是调用者的责任。同样,如果从方法中提取实例,那么通常情况是该方法创建该实例并且不会继续持有对它的类引用,在这种情况下,调用者负责管理生命周期。
答案 4 :(得分:0)
正如LukeH所说,你当前的代码中可能存在一个错误。如果您删除了using
的{{1}}语句并将其返回,则由您的方法的调用者正确地将其DataSet
正确,这是因为您的代码可以不知道何时应将其处理掉。
答案 5 :(得分:0)
即使你的调用者通过将函数调用包装在using语句中来处理返回的数据集,我认为你的函数内部仍然应该有一个try / catch块,以确保你的数据集被放置在catch块中并重新如果发生异常则抛出异常。
然而,new DataTable()
代码应包含在using语句