如果我从构造函数中抛出异常,是否会导致内存泄漏?例如以下代码:
class Victim
{
public string var1 = "asldslkjdlsakjdlksajdlksadlksajdlj";
public Victim()
{
//throw new Exception("oops!");
}
}
这些失败的对象会被垃圾收集器回收吗?
如果我从构造函数中抛出异常,是否会导致内存泄漏?例如以下代码:
class Victim
{
public string var1 = "asldslkjdlsakjdlksajdlksadlksajdlj";
public Victim()
{
//throw new Exception("oops!");
}
}
这些失败的对象会被垃圾收集器回收吗?
从不泄漏内存的角度来看,这通常是安全的。但如果您在类型中分配非托管资源,则从构造函数抛出异常是危险的。请看以下示例:
public class Foo : IDisposable {
private IntPtr m_ptr;
public Foo() {
m_ptr = Marshal.AllocHGlobal(42);
throw new Exception();
}
// Most of Idisposable implementation ommitted for brevity
public void Dispose() {
Marshal.FreeHGlobal(m_ptr);
}
}
即使您使用using块,每次尝试创建时,此类也会泄漏内存。例如,这会导致内存泄漏。
using ( var f = new Foo() ) {
// Won't execute and Foo.Dispose is not called
}
Foo
在构造函数中抛出异常,资源包装对象仍然可以被收集并适当地释放资源(尽管不是立即释放)。 - Chris Charabaruk如果您在构造函数中没有创建非托管资源,那么从构造函数中抛出异常应该是可以的。但是,如果您在构造函数中创建了非托管资源,则包括throws在内的整个构造函数体都应该被try/catch包裹起来。以下是JaredPar的一个很好的例子:
public class Foo : IDisposable {
private IntPtr m_ptr;
public Foo() {
try
{
m_ptr = Marshal.AllocHGlobal(42);
throw new Exception();
}
catch
{
Dispose();
throw;
}
}
// Most of Idisposable implementation ommitted for brevity
public void Dispose() {
Marshal.FreeHGlobal(m_ptr);
}
}
using ( var f = new Foo() ) {
// Won't execute, but Foo still cleans itself up
}
这取决于在抛出异常之前您已获取了哪些其他资源。我认为在构造函数中抛出异常并不是很好,但是在 finalizer 或 dispose() 中抛出异常要糟糕得多。