返回后,IDisposable对象会发生什么?

时间:2010-06-08 14:52:18

标签: c# .net dataset idisposable return

我有一个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返回值然后正确处理它,或者我完全错过了什么?

6 个答案:

答案 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语句