Saving a reference to an object created in the constructor initializer

Summary : if I create an object in the constructor initializer, how do I keep a reference to it so that I can refer to it later?

More details

I have a class ( LibBase , below) for which StreamWriter is required as its construction parameter. I do not have the source code for LibBase - it is in a third-party library.

 public class LibBase { public LibBase(System.IO.StreamWriter wtr) { ... } } 

I got MyClass from LibBase and in the MyClass constructor I want to pass an instance of MyWriter (a derived form of StreamWriter ) to the base class. I do it 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 needs to be disposed of, so MyClass must dispose of it (and implement IDisposable for this) , but MyClass does not have a link to the created instance of MyWriter , so I cannot dispose of it . The constructor initializer syntax does not seem to allow me to save the link.

My solution is to transcode 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 an instance of MyWriter , so I can use it later.

My questions are :

  • What am I missing here? I feel like I'm struggling with the tongue. Does C # provide a better way to do this?
  • If the language does not support this directly, is there a better solution than the method of my private constructor?
  • Any comments about defects in my solution?
+4
source share
3 answers

Your solution looks fine ... I don’t think you will miss something ...

IF you want to change the implementation (for some reason):

  • You can implement this without inheriting from LibBase , but having an instance as a private member ...
  • another option is to implement the Factory template for MyClass , which does not have an open constructor and creates a StreamWriter factory instance, etc.

BUT, as I said, there is nothing wrong with your decision (if this happens often, you should probably rethink your design).

EDIT - as per the comment:

What I mean by “creating StreamWriter factory -side”: create a Factory for MyClass so that everyone who needs an instance uses Factory ... in it you can create an instance of StreamWriter in the Factory method and pass it as a parameter to MyClass ... so you could even implement some bizarre things, such as "which instance of MyClass uses this StreamWriter instance?" or some kind of cache for instances of MyClass / StreamWriter , etc.

+2
source

I do not think that something is missing here. Your solution looks good to me if LibBase really doesn't let you get the record you passed to the constructor.

I suspect that the reason that there is no more explicit support for this is because it does not occur very often. If you find that this happens very often in your projects, you may be misusing inheritance.

To Eric Lippert Channel :

However, as I often point out, I do not need to give an excuse that you are not performing a function. Features are not cheap; they are extremely expensive, and they must not only justify their own costs, they must justify the opportunity costs so that they do not have a hundred other functions that we could do with this budget. We must justify the cost of functions for our stakeholders, but we do not need to save time and effort without introducing functions that do not correspond to our bar.

My guess is that it does not match the bar, even if it was considered desirable in the first place. (A constant value that goes beyond the cost of a C # team is the mental value of each function that C # developers absorb, and the running costs that each new function makes it potentially more difficult to add the next function.)

+5
source

I think that in this case you should not output LibBase , but delegate to it. In this case, you can obviously initialize the members in any order.

Anyone who deals with MyClass should handle the deletion, but the code written to use LibBase does not work, so you cannot just throw an instance of MyClass into the code written to handle LibBase . In such cases, inheritance is not appropriate. Of course, if LibBase doubles as an interface, you cannot really help it, in which case your workaround seems to be the best you can do.

+1
source

All Articles