There is, I think, a simpler way to do deterministic disposal of managed objects. Simply declare them without a ^
, and you'll get the same type of behavior as you would by leaving the *
off of an unmanaged C++ class: The constructor is called when the variable is initialized, and the 'destructor' (actually the Dispose method) is called when the variable goes out of scope.
When this is compiled, it turns into a try-catch-dispose if it's a local variable, or it adds a line to that class's Dispose method if it's a class field.
This is not drastically different from the auto_handle, which has a call to Dispose in it's destructor, but I think the syntax is easier to work with.
Examples:
C++/CLI:
public ref class Foo
{
AutoResetEvent are;
public:
Foo() : are(false)
{
this->are.Set(); // Use a '.' to access members.
}
void SomeMethod()
{
AutoResetEvent are2(false);
are2.Set();
}
};
Equivalent C#, from Reflector, so you can see what it's doing behind the scenes:
public class Foo : IDisposable
{
// Fields
private readonly AutoResetEvent modreq(IsByValue) are;
// Methods
public Foo()
{
AutoResetEvent modopt(IsConst) event2 = new AutoResetEvent(false);
try
{
this.are = event2;
base..ctor();
this.are.Set();
}
fault
{
this.are.Dispose();
}
}
public void ~Foo()
{
}
public sealed override void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
[HandleProcessCorruptedStateExceptions]
protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool flag1)
{
if (flag1)
{
try
{
this.~Foo();
}
finally
{
this.are.Dispose();
}
}
else
{
base.Finalize();
}
}
public void SomeMethod()
{
AutoResetEvent are2 = null;
AutoResetEvent modopt(IsConst) event2 = new AutoResetEvent(false);
try
{
are2 = event2;
are2.Set();
}
fault
{
are2.Dispose();
}
are2.Dispose();
}
}