C#:IDisposable 类需要“使用”条款?

发布于 2024-10-19 20:26:24 字数 149 浏览 4 评论 0原文

如果我使用 IDisposable 类,我是否应该始终使用 using 子句,例如:

using (MyClass myclass = new MyClass())
{
...
}

If am using an IDisposable class, should I always use a using clause, for example:

using (MyClass myclass = new MyClass())
{
...
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

仲春光 2024-10-26 20:26:24

using 语句确保即使发生异常或对象超出范围,也会调用 Dispose 来释放资源。

这比使用以下代码块更简单,

try
{
   ...
}
catch()
{
   // Handle exception
}
finally
{
    // Free resources by calling Dispose()
}

注意
如果不想处理异常,则不需要catch 块。在这种情况下,一个 try...finally 块就足够了(正如其他答案中指出的那样)。

替代方式
您可以在同一个 using 语句中创建一次性对象的多个实例,例如

using(MyClass myclass1 = new MyClass(), 
      MyClass myclass2 = new MyClass())
{
    ...
}

示例
理解 C# 中的 'using' 语句

using (MyResource myRes = new MyResource())
{
    myRes.DoSomething();
}

被翻译为(由 CLR

MyResource myRes= new MyResource();
try
{
    myRes.DoSomething();
}
finally
{
    // Check for a null resource.
    if (myRes!= null)
    {
        // Call the object's Dispose method.
        ((IDisposable)myRes).Dispose();
    }
}

您可以查看在示例开头指定的链接中生成了 MSIL

更多信息

The using statement ensures that Dispose is called to free the resources even if an exception occurs or if the object goes out of scope.

This is simpler than using the following code block,

try
{
   ...
}
catch()
{
   // Handle exception
}
finally
{
    // Free resources by calling Dispose()
}

Note
The catch block is not necessary if one does not want to handle the exception. In that case, a try...finally block would suffice (as pointed in other answers).

Alternative way
You can create multiple, instance of the disposable object in the same using statement, for example

using(MyClass myclass1 = new MyClass(), 
      MyClass myclass2 = new MyClass())
{
    ...
}

Example
From Understanding the 'using' statement in C#

using (MyResource myRes = new MyResource())
{
    myRes.DoSomething();
}

gets translated to (by the CLR)

MyResource myRes= new MyResource();
try
{
    myRes.DoSomething();
}
finally
{
    // Check for a null resource.
    if (myRes!= null)
    {
        // Call the object's Dispose method.
        ((IDisposable)myRes).Dispose();
    }
}

You can have a look at the generated MSIL in the link specified at the beginning of the example.

More information

难理解 2024-10-26 20:26:24

它使其代码更具可读性。因此,通常您应该在 using 块中声明并实例化该对象。它确保即使发生异常也会调用 Dispose 方法。在编译时,相同的表达式将类似于这样

{
  MyClass myclass = new MyClass ();
  try {
    //Do something with myclass
  }
  finally {
    if (myclass != null)
      ((IDisposable)myclass).Dispose();
  }
}

It makes it much more readable code. So, as a rule you should declare and instantiate the object in a using block. It ensures that the Dispose method is called even if an exception happens. At compile time the same expression would look something like this:

{
  MyClass myclass = new MyClass ();
  try {
    //Do something with myclass
  }
  finally {
    if (myclass != null)
      ((IDisposable)myclass).Dispose();
  }
}
情深缘浅 2024-10-26 20:26:24

如果一个类实现了IDisposable,那么当您处理完该对象后,您应该始终调用Dispose。 C# 提供了 using 语句作为语法糖,以简化此操作。因此,不需要使用 using 来调用 Dispose。也就是说,它是调用 Dispose 的事实上的标准方法。即,如果您的代码没有使用 using 而是在finally 块中调用Dispose,那么对于经验丰富的编码人员来说,它看起来会有点奇怪。

using 块的扩展(假设 MyClass 是引用类型)是:

{
    MyClass myclass = new MyClass();
    try {
        //...
    }
    finally {
        if (myclass != null) ((IDisposable)myclass).Dispose();
    }
}

using 版本更易于编码且更易于阅读。

If a class implements IDisposable you should always call Dispose when you are done with the object. C# provides the using statement as syntactic sugar to make this easier. So, it's not required to use using to call Dispose. That said, it is the de facto standard way to invoke Dispose. i.e. if your code is not using using and is instead invoking Dispose in finally blocks it will look a bit odd to experienced coders.

The expansion of your using block (assuming MyClass is a reference type) is:

{
    MyClass myclass = new MyClass();
    try {
        //...
    }
    finally {
        if (myclass != null) ((IDisposable)myclass).Dispose();
    }
}

The using version is easier to code and easier to read.

百善笑为先 2024-10-26 20:26:24

简单地说,如果它实现了 IDisposable,并且您希望调用该方法(也在您执行操作时的 finally 块中出现异常时)。请使用 using。GC

不会为您调用 Dispose()!有些类实现了终结器 ~ClassName () 但尽量避免这种情况,因为它有很多副作用并且不明显,

您可以将 using 语句读为:

TestClass test = new TestClass();
try
{
      test.DoSomething();
}
finally
{
      test.Dispose();
}

Simply put, if it implements IDisposable, and you want to have that method called (also on exceptions in the finally block when you are doing. Use using.

The GC will NOT call Dispose() for you! Some classes implement a finalizer ~ClassName() but try to avoid this because it has many side effects and is not obvious.

You can read an using statement as:

TestClass test = new TestClass();
try
{
      test.DoSomething();
}
finally
{
      test.Dispose();
}
榆西 2024-10-26 20:26:24

只要对象的生命周期足够短,您就应该始终这样做。有时,您必须单独处理清理工作,因为您的对象具有较长的生命周期,这些对象在代码块完成后仍将持续很长时间。

You should always do it so long as the lifetime of the object is short enough that this is possible. Sometimes you have to handle the cleanup separately because you have objects with a long lifetime that will persist long after the block of code is done.

醉城メ夜风 2024-10-26 20:26:24

创建 IDisposable 对象时存在三种情况:

  1. 该对象将在一段时间内被需要,但在当前代码块退出后将不再需要。
  2. 该对象将被提供给当前例程的调用者,然后由当前例程的调用者负责。
  3. 负责 IDisposable 对象的类将其存储在一个字段中,以便在将来的方法/属性调用中使用。

在场景#1中,使用“using”块来创建对象;其清理工作将自动进行。

在场景 #2 中,使用带有“ok”变量的“try-finally”块,该变量最初设置为“False”,但在“try”结束时或在任何返回之前设置为“True”;最后,如果“oK”为 false,则调用 Dispose 以确保部分构造的对象得到清理。

在场景 #3 中,对象创建后立即将其存储在字段中,并定义一个 IDisposable.Dispose 方法,该方法会将字段中的值复制到变量中,将字段清空,如果变量非空,处理它(如果有可能多个线程同时调用 Dispose,请使用 Interlocked.Exchange 来锁定并清除该字段)。构造函数也应该像场景 #2 中的函数一样受到保护。

There are three scenarios when an IDisposable object is created:

  1. The object will be needed for a little while, but won't be needed after the current block of code exits.
  2. The object will be given to the caller of the current routine, which will then be responsible for it.
  3. The class which is responsible for the IDisposable object stores it in a field so it will be available for use in future method/property calls.

In scenario #1, use a "using" block to create the object; its cleanup will be handled automatically.

In scenario #2, use a "try-finally" block with an "ok" variable that's set to "False" initially but is set to "True" at the end of the "try" or just before any return; in the finally, if "oK" is false, call Dispose to ensure the partially-constructed object gets cleaned up.

In scenario #3, store the object in a field as soon as it's created, and define an IDisposable.Dispose method which will copy the value in the field to a variable, null out the field, and if the variable was non-null, Dispose it (if there's any possibility of multiple threads calling Dispose simultaneously, use Interlocked.Exchange to latch and clear the field). Constructors should also be protected as would functions in scenario #2.

究竟谁懂我的在乎 2024-10-26 20:26:24

using 子句是以下代码块的语法糖:

MyClass myclass = null;
try
{
     myclass = new MyClass();
     //do work
}
finally
{
     if(myclass != null)
          myclass.Dispose();
}

如果类实现了 IDisposable,则应确保在使用完它后调用 Dispose。 using 子句只是一种简单的方法。所以你不必使用“using”来做到这一点,但你应该确保它被调用。

the using clause is syntax sugar on the following code block:

MyClass myclass = null;
try
{
     myclass = new MyClass();
     //do work
}
finally
{
     if(myclass != null)
          myclass.Dispose();
}

If a class implements IDisposable you should ensure that Dispose is called when you are done using it. The using clause is just an easy way to do it. So you don't have have to use "using" to do it, but you should ensure that it is called.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文