C#编译器会自动处理IDisposable对象吗?

C#编译器会自动处理IDisposable对象吗?,c#,.net,idisposable,compiler-optimization,C#,.net,Idisposable,Compiler Optimization,假设我有一个方法publicstaticrectangledrawrectangle(向量原点,向量大小),它返回类型为Rectangle:IDisposable 如果我只调用方法DrawRectangle(origin,size),但不将返回值赋给变量myRectangle=DrawRectangle(origin,size),编译器会自动检测到这一点并调用DrawRectangle(origin,size).Dispose(),还是我必须自己做?否.点 最终,终结器会执行,但不会。它不会自动

假设我有一个方法
publicstaticrectangledrawrectangle(向量原点,向量大小)
,它返回类型为
Rectangle:IDisposable

如果我只调用方法
DrawRectangle(origin,size)
,但不将返回值赋给变量
myRectangle=DrawRectangle(origin,size)
,编译器会自动检测到这一点并调用
DrawRectangle(origin,size).Dispose()
,还是我必须自己做?

否.点


最终,终结器会执行,但不会。它不会自动调用Dispose。

如果您的
矩形
类实现了
IDisposable
,请在可行时尝试
使用(){…}
语句


如果希望CLR调用Dispose方法,通常建议在类中实现所谓的。但是,我不会依赖CLR,也不会等待GC收集对象并使用子句。

编译器将代码构建到程序集中,并且不负责任何执行。net运行时是运行代码的,更具体地说,垃圾收集器处理内存清理。通常,最好的做法是在using块内部调用实现IDisposable的对象。例如:

使用(var obj=新对象) { 做你的事 }


这将有助于运行时理解对象何时超出范围并提前清理,但只要您不保留对对象的引用,运行时最终将清理对象并为您处置它。

我只能想到两种情况,编译器会自动调用dispose;最明显的是:

using(var obj = ... )
{
  // some code
}
这是一条明确的指令,表示“最后,无论成功还是失败,如果
obj
为非空,请调用
obj.Dispose()
”。基本上,它扩展到:

{
   var obj = ...
   try {
       // some code
   } finally {
       if(obj != null) obj.Dispose();   
   }
}
另一个是
foreach
,迭代器在其中进行处理-尽管它变得有点复杂,因为
IEnumerator
没有指定需要
IDisposable
(相反,
IEnumerator
确实指定了这一点),从技术上讲,
IEnumerable
甚至不需要
foreach
,但基本上:

foreach(var item in sequence) {
   // some code
}
可以表示为(尽管规范可能会略有不同):

在所有其他情况下,处理资源是您的责任


如果不确保调用了
Dispose()
,那么在GC最终收集对象之前不会发生任何事情如果存在终结器(不一定存在,而且通常不存在),将调用终结器-但这与
Dispose()
不同。它可能会(取决于每种类型的实现)最终执行与
Dispose()
相同的操作:但它可能不会。

我还要提到,编译器从不处理正在编译的代码,只有CLR。终结器可以调用
Dispose
,但它当然不必这样做。处置和终结/垃圾收集是分开的。@ErikPhilips meh;我不确定这是一个有用的区别。当然,在某些地方,编译器会添加一个
Dispose
foreach
使用
是我的head@TomTomGC只是清理内存,如果有内存,则调用finalize;它从来没有做过任何与
IDisposable
/
Dispose()
-虽然终结器实现可能(如果它选择)在某些方面,但我认为终结器的可用性可能弊大于利,因为它们通常都没有正确编写以“大部分工作”的代码。终结器应该重要的唯一时间是在执行诸如插入实现
IDisposable
的不可变对象(例如,保存预渲染图片的位图)之类的操作时,在这种情况下,它们可以与
WeakReference
合理组合。在一些情况下,正确的清理非常困难(例如,基类对象创建一个
IDisposable
,然后派生类构造函数抛出一个异常),但是…“否”和“使用
using
”。标记为重复:@igrimpe不确定它是重复的;这个问题特别询问编译器如果集合返回的枚举器的类类型没有实现
IDisposable
(与类型
IEnumerator
)相反,我相信C#会假设枚举器实例没有实现
IDisposable
,并且不会尝试强制转换,尽管实际返回的实例可能是实现
IDisposable
@supercat yes的派生类型,但我注意到:请参见“技术上”。等价物示例旨在说明和语义等价,而不是精确的实现。作为doe,它是否尝试对子类型场景进行强制转换:我必须查看reflector以进行评论。在我自己的IL生成器中,我只禁用了密封的/struct,因此不能有子类。如果
GetEnumerator
返回的类型实现了
IDisposable
,那么编译器将对其调用
Dispose
。遗憾的是,据我所知,编译器将查找的唯一名称是
GetEnumerator
,因为如果它查找例如
GetForEachEnumerator
,则可能返回一个未实现任何接口的结构(因此不必实现
IDisposable
),虽然
GetEnumerator
可以返回一个实现了
IEnumerator
的类,因此必须实现
IDisposable
@supercat,但您可以使用显式+公共实现来实现,IIRCOne可以做到这一点,如果您愿意要求希望使用
IEnumerator
的用户首先强制转换为
IEnumerable
,或者调用名为oth的方法
{
    var iter = sequence.GetEnumerator();
    using(iter as IDisposable)
    {
        while(iter.MoveNext())
        {   // note that before C# 5, "item" is declared *outside* the while
            var item = iter.Current;
            // some code
        }
    }
}