C# 创建和内联使用一次性对象安全吗?

C# 创建和内联使用一次性对象安全吗?,c#,C#,例如,我见过很多次开发人员使用一次性对象内联。我的意思是: var result = new DataTable().Compute("1 + 4 * 7", null); 我知道不会调用Dispose方法,但是由于没有对对象的引用,垃圾收集器将如何处理它?使用这样的一次性物品安全吗 我在示例中使用了一个DataTable,因为这是我找到的唯一具体示例,但我的问题一般适用于一次性对象。我个人并不是这样使用它们的,我只是想知道如果它们以这种方式使用,GC是否会对它们进行不同的处理。如果内联初始化

例如,我见过很多次开发人员使用一次性对象内联。我的意思是:

var result = new DataTable().Compute("1 + 4 * 7", null);
我知道不会调用
Dispose
方法,但是由于没有对对象的引用,垃圾收集器将如何处理它?使用这样的一次性物品安全吗


我在示例中使用了一个
DataTable
,因为这是我找到的唯一具体示例,但我的问题一般适用于一次性对象。我个人并不是这样使用它们的,我只是想知道如果它们以这种方式使用,GC是否会对它们进行不同的处理。

如果内联初始化的对象实现了析构函数,则该析构函数可能会在对象超出范围后调用Dispose()


但是,更干净、正确的方法是使用using语句,因为这可能只会导致对象的实例毫无目的地挂起

以这种方式使用一次性物品是不安全的。是的,不会持有任何引用,但一次性模式的目的是处置所有无法垃圾收集的非托管资源(如操作系统句柄)

这里的关键问题是调用
Dispose
的时间,这在您的示例中是未知的(提供了
IDisposable
的良好实现-请参见下文)。我会考虑使用<代码> IDISPABLE < /Calp>实例,不使用<代码>使用< /Cord>语句。代码气味。该类实现IDisposable是有原因的,因此作为用户,您应该遵守它的约定

但是,请注意,在IDisposable的类中,类的终结器处理未处理对象的处理。因此,即使未使用在
内实例化,也应在未知时间和不同(GC)线程上执行处置

我只是想知道GC是否以这种方式处理它们


不,GC对所有对象都一视同仁,对IDisposable实现的处理也没有任何不同。然而,在
IDisposable
的正确实现中,
Finalize
方法(由GC在每个对象上调用,除非在每个对象的基础上被抑制)调用将导致调用
Dispose

,尽管这并不能回答您的一般问题,它确实说明了您的示例,该代码段是由一个聪明的程序员编写的,他知道DataTable没有任何可丢弃的东西,并且实际上没有实现Dispose()。许多.NET程序员对此感到非常不安。所以不要这样做,当你使用using语句时,它不会变得更丑陋。你可以为自己从未犯错而感到欣慰。C#对象没有析构函数。他们可能有终结器。当对象超出范围时,终结器不会运行。当GC认为是时候运行它们时,它们就会运行。在您的链接中:“程序员无法控制何时调用析构函数,因为这是由垃圾回收器决定的。”他们使用“析构函数”一词来描述终结器可能会让人困惑。另请参见。还应注意,如果类具有终结器(C#术语中的析构函数),则垃圾收集器不会在下一代0 collect中立即收集此实例。相反,它会将实例添加到终结器队列中,并且在下一代1 collect之前不会完成对该实例的收集。因此,根据终结器(析构函数),即使您知道它存在并正确实现,也可能导致性能下降。此外,正如其他人所说,最好现在就释放这些资源,而不是等待可能的垃圾收集发生。@ruakh问得好!我想我是假设
Dispose()
方法调用
GC.SuppressFinalize(this)
。只要存在析构函数,就应该如此。在这种情况下,对
Dispose()
的调用将确保立即收集,并且没有终结队列。如果没有像那样显式地抑制终结,那么您是绝对正确的:无论哪种方式,性能都会受到影响。人们经常感到惊讶的是,仅仅存在一个析构函数,即使是一个空的身体,也会损害性能。我不得不同意。尽管有些类不显式处置相对无害,但这似乎是一个很糟糕的习惯。如果不提前显式调用
IDisposable.dispose()
,则在垃圾收集过程中释放非托管资源。当然,这假定
IDisposable
实现正确,并且终结器释放非托管资源。因此,当一次性物品不再使用时,不处理它,并将其交给垃圾收集器清理,实际上是“安全的”。然而,它不是非常聪明或高效。