Summary: if I create an object in a constructor initialiser, how do I keep a reference to it so I can reference it later?
Details:
I have a class (LibBase
, below) that requires a StreamWriter
as its construction parameter. I don't have the source code for LibBase
- its in a third-party library.
public class LibBase
{
public LibBase(System.IO.StreamWriter wtr) { ... }
}
I have derived MyClass
from LibBase
and in the MyClass
constructor I want to pass an instance of MyWriter
(derived form StreamWriter
) to the base class. I do this as follows.
public class MyWriter : System.IO.StreamWriter
{
public MyWriter(int n) { ... }
// Contains unmanaged resources
}
public class MyClass : LibBase
{
public MyClass(int n)
: LibBase(new MyWriter(n))
{ }
}
The problem is that MyWriter
requires disposing, so MyClass
should dispose it (and implement IDisposable
to do this) but MyClass
doesn't have a reference to the created MyWriter
instance, so I can't dispose it. The syntax for the constructor initialiser doesn't seem to permit my to keep a reference.
My solution is to re-code MyClass
as follows:
public class MyClass : LibBase, IDisposable
{
public MyClass(Encoding enc)
: this(new MyWriter(enc))
{ }
private MyClass(MyWriter wtr)
: LibBase(wtr)
{ this.wtr = wtr; } // store reference
private MyWriter wtr;
// (implement IDisposable using wtr member variable
}
The private constructor stores a reference to the MyWriter
instance so I can dispose it later.
My questions:
I don't think you're missing anything here. Your solution looks okay to me if LibBase
really doesn't let you get at the writer you passed in to the constructor.
I suspect that the reason there isn't more explicit support for this is that it doesn't crop up very often. If you find it cropping up very often in your designs, it's possible that you're overusing inheritance.
To channel Eric Lippert:
However, as I often point out, I don't have to provide a justification for not doing a feature. Features aren't cheap; they are extremely expensive and they must not only justify their own cost, they must justify the opportunity cost of not doing the hundred other features we could have done with that budget. We must justify the cost of features to our stakeholders, but we need not justify saving time and effort by not implementing features that don't meet our bar.
My guess this is something which doesn't meet the bar, even if it were deemed desirable in the first place. (There's ongoing cost beyond the cost to the C# team - there's the mental cost of each feature being absorbed by C# developers, and the ongoing cost that each new feature makes it potentially harder to add the next feature.)
Your solution seems ok... I don't think that you miss anything...
IF you want to change the implementation (for whatever reason):
LibBase
but having an instance as a private member... MyClass
thus having no public constructor and creating the StreamWriter
instance factory-side etc.BUT as I said there is nothing wrong with you solution (if it happens often you probably should rethink your design).
EDIT - as per comment:
What I mean by "creating StreamWriter factory-side" is: create a Factory for MyClass
so that anyone needing an instance uses the Factory... therein you can create the StreamWriter
instance in the Factory method and pass it in as param to MyClass
... this way you could even implement some fancy things like "which MyClass
instance is using a given StreamWriter
instance ?" or some sort of a cache for MyClass
/ StreamWriter
instances etc.
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