【问题标题】:Is it valid to use properties of Disposing object使用 Disposing 对象的属性是否有效
【发布时间】:2014-11-20 04:01:10
【问题描述】:

谁能告诉我使用 Disposing 对象的属性是否有效?例如在下面的代码中,DataTable 正在获取 Dispose 但其属性 DefaultView 稍后使用,

public DataView MyView { get; set; }

    private void button2_Click(object sender, EventArgs e)
    {

        using (DataTable table = new DataTable())
        {
            using (DataColumn dc = new DataColumn("s"))
            {
                table.Columns.Add(dc);
                MyView = table.DefaultView;

            }
            Debug.Write(table.Columns[0].ColumnName);
        }
    }

如果我使用 MyView,我不会收到任何错误。但是在这种情况下,Disposing 对象是否会释放其所有属性 DefaultView。

【问题讨论】:

  • 一般情况下,请勿触摸已处置的物体。你碰巧用DataTable 侥幸逃脱。不要养成这个习惯。
  • 以后用在哪里?它超出了using 语句的范围,因此以后无法使用。
  • 你是 100% 正确的。绝对应该期望引用“dc”指向的托管资源具有这种行为方式。引用本身不存在,也无法访问。

标签: c# .net using-statement


【解决方案1】:

这取决于类型,但作为一般规则,您应该只在使用完对象后才调用Dispose()。如果您在处置对象后尝试访问任何成员,大多数IDisposable 实现都会抛出ObjectDisposedException

IDisposable 本身并没有强制实现类在处置时对所有成员的所有访问权无效。

只有当类型特别 证明它允许你在处理它之后调用某些成员时,你才应该考虑这样做。就个人而言,我会尽量避免使用以这种方式实现的类型。

请注意,这与对象本身有关,不一定是它引用的对象。也就是说,仅仅因为对象A 具有引用其他对象B 的属性,这并不意味着对象B 在您处理A 时变得无法使用。

一个很好的例子是NetworkStream 类,它有一个Socket 属性。如果您将NetworkStream 对象初始化为不拥有传递给其构造函数的Socket 实例,那么Socket 实例在处理NetworkStream 后仍然有效,这很好。

【讨论】:

    【解决方案2】:

    DataTableDataColumn 基类 实现了IDisposable,但它们的实现不做任何事情。这些实现了IDisposable,因为派生的类可能需要处理资源。

    例如,在过去,我编写了一个通用的强类型 DataTable 类。它确实封装了数据库连接,或者可能是一个流。在那种情况下,Dispose 确实做了一些事情。

    【讨论】:

      【解决方案3】:

      IDisposable 接口是在您拥有非托管资源时实现的,如果在释放这些资源之前引发异常,可能会导致问题。

      当在 using 块中使用时,编译器会生成

      try{... } 
      catch{... } // may be empty, I can't recall at the moment 
      finally 
      {
         Dispose() ;
      } 
      

      由于您添加的值不是非托管资源,因此没有理由假定它已被处置。对象的引用仍然有效,因此 GC 不会清除内存。仔细想想,如果引发异常,那就更可怕了。

      C# 在底层具有内存管理功能,因此对于许多程序员来说,它是遥不可及的。当然有些东西在野外实施得很糟糕,因为资源管理不是你在 c# 中经常考虑的事情

      【讨论】:

      • 这不是IDisposable何时使用的问题。这是什么时候实施的问题。
      • 好吧,我只是想建议您在访问 MyView 时仍然有有效的参考。 'IDisposable' 用于释放 GC 不知道的 非托管 资源。您要质疑的引用是托管资源,不需要任何工作来确保正确处理资源,因为 GC 非常有效。问题中有我不理解的地方吗?
      • 您不了解IDisposable 的关键部分。一般来说,如果一个类实现了那个接口,就意味着这个类需要你调用Dispose()。通常的原因是非托管资源。然而,第二次猜测类设计者的意图并不是一个好主意,你似乎正在这样做。将您的问题与DataTable 联系起来,让我们看看它是否会变得更好。
      • 如果类设计者打算明确释放托管资源,他们没有正确使用接口。 Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector. The consumer of an object can call this method when the object is no longer needed. 来源:msdn.microsoft.com/en-us/library/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-10
      • 1970-01-01
      • 2010-12-04
      • 2012-01-05
      • 2017-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多