2010-08-23 132 views
5

如果我使用的是using关键字,还需要执行IDisposable吗?using关键字和IDisposable接口之间的关系是什么?

+3

也许你的意思是要问的是,“如果我使用‘使用’关键字,做我仍然必须调用Dispose()? – 2010-08-23 04:40:51

+3

如果你是,你已经是 – 2010-08-23 05:01:35

+4

@Chris Farmer ...很好的编辑我开始认为这是@Apple的新垃圾压缩机!!! – user279521 2010-08-23 13:40:08

回答

12

如果使用using statement封闭型必须已经实现IDisposable否则编译器会发出错误。因此,考虑使用IDisposable实现是一个先决条件。

如果要在自定义类上使用using声明,则必须为其实施IDisposable。然而,这是一种倒退,因为没有理由这样做。只有当你有东西需要处理像非托管资源,你应该实施它。

// To implement it in C#: 
class MyClass : IDisposable { 

    // other members in you class 

    public void Dispose() { 
     // in its simplest form, but see MSDN documentation linked above 
    } 
} 

这使您可以:

using (MyClass mc = new MyClass()) { 

    // do some stuff with the instance... 
    mc.DoThis(); //all fake method calls for example 
    mc.DoThat(); 

} // Here the .Dispose method will be automatically called. 

有效这是相同的文字:

MyClass mc = new MyClass(); 
try { 
    // do some stuff with the instance... 
    mc.DoThis(); //all fake method calls for example 
    mc.DoThat(); 
} 
finally { // always runs 
    mc.Dispose(); // Manual call. 
} 
+0

你能展示一个代码示例吗? – Troy 2010-08-23 04:37:57

+1

@Troy:添加示例以突出说明。 – 2010-08-23 04:42:08

+2

实际上,它对于每当有必须/应该在finally节中执行某些内容的“三明治”代码时都是非常有用的模式。例如,一个常见的场景是繁忙的光标,步骤是... 1. /复制现有的光标 2. /设置光标到您的等待光标 3.在最后一节复制原始。 随着使用和IDisposable接口,你可以使用,然后写代码类似 (Busy.WaitCursor) {// 哪里WaitCursor是返回忙构造副本,集和处置的实例的静态属性()重新集。 } – 2010-08-23 04:50:09

5

你是令人困惑的事情。你只能在实现IDisposable的东西上使用“using”关键字。

编辑:如果使用using关键字,则不必显式调用Dispose,它将在using块的结尾自动调用。其他人已经发布了如何将using语句翻译为try-finally语句的示例,并在finally块中调用Dispose。

+0

从记录集读取数据时,您可以使用“使用”关键字,对吗? – Troy 2010-08-23 04:33:11

+1

@Troy,是的,这是因为IDataReader实现了IDisposable。 – 2010-08-23 04:36:44

+0

只有在包装你的记录集时才实现IDisposable。如果它编译,那么它实现IDisposable .... – 2010-08-23 04:37:50

2

使用将只处置一次性对象。因此,在未实现IDisposable 的对象周围封装使用块是相当无用的.实际上会导致编译器错误。

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.

+1

事实上,这是一个编译器错误。 – Timwi 2010-08-23 04:33:26

12

你不能有一个没有其他。

当你写:

using(MyClass myObj = new MyClass()) 
{ 
    myObj.SomeMthod(...); 
} 

编译器会产生这样的事情:

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

因此,大家可以看到,同时具有using关键字假定/要求IDisposable的实现。

+0

+1,但没有假定 - 需要。如果类型没有实现IDisposable,那么您在此处显示的编译器代码除非有无效的转换异常。这就是为什么编译器通过给出编译时错误来防止这种情况发生的原因,从而使得在使用中使用IDisposable是必需的,而不是假定的。 – 2010-08-23 12:48:29

+0

@Jimmy是的,你说得对,说我认为我的意思。答案已更新。 – Incognito 2010-08-23 13:02:20

4

是,则使用关键字是对于这种类型的图案的语法糖...(从MSDN)

Font font1 = new Font("Arial", 10.0f); 
    try 
    { 
    byte charset = font1.GdiCharSet; 
    } 
    finally 
    { 
    if (font1 != null) 
     ((IDisposable)font1).Dispose(); 
    } 

编辑:一个有用的例子。

当你发现你正在做的事情在最后一节consistantly,例如已经将其设置为等待光标后重置光标回其默认,这是该模式的候选者...

public class Busy : IDisposable 
    { 

    private Cursor _oldCursor; 

    private Busy() 
    { 
     _oldCursor = Cursor.Current; 
    } 

    public static Busy WaitCursor 
    { 
     get 
     { 
     Cursor.Current = Cursors.WaitCursor; 
     return new Busy(); 
     } 
    } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     Cursor.Current = _oldCursor; 
    } 

    #endregion 
    } 

被称为像...

using(Busy.WaitCursor) 
{ 
    // some operation that needs a wait cursor. 
} 
1

using关键字已经实现,因此,如果您使用using关键字,你不必调用IDisposable的

1

您必须实现IDisposable使用使用。如果您尝试使用()上的类型不实现IDisposable使用您会收到以下编译时错误:

error CS1674: 'SomeType': type used in a using statement must be implicitly convertible to 'System.IDisposable' 
相关问题