In item 5 of More Effective C#, the following is presented:
public class EngineDriver<T> where T : IEngine, new()
{
public void GetThingsDone()
{
T driver = new T();
using (driver as IDisposable)
{
driver.DoWork();
}
}
}
The goal here is to properly dispose of drive, if it implements IDisposable
. This makes sense, but how is this implementation different from the more succinct:
public class EngineDriver<T> where T : IEngine, new()
{
public void GetThingsDone()
{
using (T driver = new T())
{
driver.DoWork();
}
}
}
Shouldn't the code above behave in exactly the same way? In fact, isn't the original code dangerous in that the lifetime of driver is beyond the using block, but driver is disposed of at the end of said block?
No, because T does not necessarily implement IDisposable
(unless IEngine
itself implements it) - the second will not compile in this case, whereas the first will.
Regarding the scope of driver - it will still be accessible after the using block in the second example which is not ideal, and attempting to do so would usually result in an exception. Ideally you should have IEngine
implement IDisposable
or add an additional constraint to EngineDriver
that T implement it.
It is kinda important that you use the tools that are available to you. Compile your proposed code. I'll wait a few minutes.
Okay, you're back. Yes, you need to add a constraint for IDisposable so that the using statement is always capable of disposing the object. The code from the book is a hack around that restriction, it will work even if T does not implement IDisposable. using (null) {} is valid.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With