0

我在互联网上搜索这个并没有成功。所以希望这里有人可以回答我,因为我不明白它的意义。

  • 这只是一种好的做法还是它实际上做了一些事情?
  • 如果 .NET 有非常好的垃圾收集器,我为什么要打扰?

例子

在这个例子中,我将使用超级简单的数据注释验证过滤器。封装我的数据上下文有什么好处using

public static ValidationResult ValidateUniqueUsername(string username, object context)
{
    using (var db = new MainDataContext()) // What's the point?
    {
        var user = db.Users.SingleOrDefault(x => x.Username == username);

        if (user == null) return ValidationResult.Success;
        return new ValidationResult("Username already taken");
    }
}
4

5 回答 5

2

using子句基本上是这样展开的:

ISomeDisposable disposable = new SomeDisposable();
try
{
    // your code here
}
finally
{
    if(disposable != null)
        disposable.Dispose();
}

因此,如您所见,如果您的代码抛出异常,则一次性对象是 Disposed。如果您不抛出异常,它仍然会被处理(因此使用finally块)。它确保您的对象被处置

于 2013-08-12T10:30:30.837 回答
1

using块只是块的语法糖Try...Finally。所以你的代码相当于这个

MainDataContext db = new MainDataContext();
try
{
   var user = db.Users.SingleOrDefault(x => x.Username == username);

   if (user == null) return ValidationResult.Success;
       return new ValidationResult("Username already taken");
}
finally
{
    if (db != null)
      ((IDisposable)db).Dispose();
}

这意味着无论return调用如何,都会调用 db 的Dispose方法(因为它在一个finally块中)。一般来说,处置任何实现IDisposable它是否是托管的对象总是一个好主意。虽然有一些例外。

在托管场景中,这可能太重要也可能不太重要,尽管我建议坚持最佳实践,但Dispose主要用于unmanaged资源。这些资源可能会保留,从而导致内存泄漏,这就是为什么在使用完它们后将它们处理掉是个好主意。来自MSDN

该接口的主要用途是释放非托管资源。当不再使用该对象时,垃圾收集器会自动释放分配给托管对象的内存。但是,无法预测垃圾收集何时发生。此外,垃圾收集器不了解非托管资源,例如窗口句柄或打开的文件和流。

于 2013-08-12T10:32:19.817 回答
1

有些物品是一次性的。这意味着他们使用不在 GC 范围内的外部资源(文件指针、套接字)(较低级别的资源)。

这些资源需要在持有它们的对象被销毁之前被释放(释放)。如果对象被 GC 删除而之前没有调用 dispose 方法,它们可能会导致内存泄漏。

using 块负责在块的末尾自动调用 dispose。它类似于:

Obj obj;
try{
      obj = new Obj();
      //code
}
catch(Exception e){
      //error
}
finally{
      obj.Dispose();
}

Obj 类必须实现 Disposable 接口才能成为一次性的。using 块不能与非一次性对象一起使用(至少在 C# 中)。

在 using 块内使用一次性对象通常是一种很好的做法。

于 2013-08-12T10:33:11.910 回答
0

将数据封装在“使用”中可确保对象在超出“使用”范围时立即被处理掉。

另一方面,垃圾收集器在确定对象超出范围或不再需要时处置对象。

以 MSDN 的方式: Using 提供了一种方便的语法,可确保正确使用IDisposable 对象。

正如另一个答案所说,@(Moo-Juice)

“它确保你的对象被处置。”

于 2013-08-12T10:29:50.293 回答
0

首先 - 阅读IDisposable模式及其用途。注意第一句话:

该接口的主要用途是释放非托管资源。

这才是重点。垃圾收集是关于实现内存而不是资源。这是IDisposable提供帮助的地方。阅读垃圾收集基础的操作非托管资源一章。请注意:

如果您的托管对象通过使用其本机文件句柄来引用非托管对象,则您必须显式释放非托管对象,因为垃圾收集器仅跟踪托管堆上的内存。

垃圾收集是一种不确定的机制。你可以在你的类中声明一个终结器,但你不能确定它什么时候会被调用。因此,您的非托管资源可以毫无理由地被保留。

于 2013-08-12T10:31:02.723 回答