Reputation: 2347
According to this article, fields are initialized before execution of constructors. However, what if an exception is throw in a constructor? The object instantiation would fail.
But what would happen to the initialized fields? Do they still remain in memory or are they garbage collected immediately? What if there is an unmanaged resource declared and initialized before the exception in the constructor occurs. Will this unmanaged resource survive?
Upvotes: 4
Views: 1301
Reputation: 81189
If construction of an object requires the acquisition of resources, the only way to prevent resources from leaking if the constructor throws for any reason is to require that all object construction be performed using a factory method which can take care of object cleanup in the event that something goes wrong. Unfortunately, .NET does not do anything to make this convenient. One approach would be something like:
static public MyThing Create(...)
{
var cleanupList = new List<IDisposable>();
try
{
MyThing Result = new MyThing(cleanupList, ...); // private or protected constructor
}
finally
{
if (Result == null)
{
List<Exception> failureList = null;
foreach (IDisposable cleaner in cleanupList)
{
try
{
cleaner.Dispose();
}
catch(Exception ex)
{
if (failureList == null)
failureList = new List<Exception>();
failureList.Add(ex);
}
}
if (failureList != null)
throw new FailedConstructorCleanupException(failureList);
}
}
}
If there is a failure while performing the Dispose
operations, the FailedConstructorCleanupException
really should encapsulate the exception from the thrown constructor, but when cleanup succeeds the constructor-failure exception should pass through the wrapper without being caught and rethrown. Unfortunately, while VB.NET makes it possible for a Finally
block to know what exception was thrown in the Try
without having to catch and rethrow, C# doesn't.
Upvotes: 1
Reputation: 203834
Collection of the type is no different if an exception is thrown in the constructor than it would be if there weren't. When the GC runs, if the object isn't accessible from a rooted item, it'll be cleaned up. If you have no references to the object due to its failed initialization, it'll be cleaned up at the next collection.
Unmanaged resources are not cleaned up on their own. That's literally the definition of an unmanaged resource. Unmanaged resources are anything that aren't cleaned up on their own; managed resources are resources that are cleaned up on their own. When dealing with unmanaged resources you need to support the case of failed initialization of a type and clean up the resources appropriately, if you do not, then you have leaked them, and will need to deal with whatever the consequences of that are.
Upvotes: 3