Design best practice - should an object own what is passed to its constructor?

I have the following class:

public class SqlCeEventStore: EventStore { private EventStoreDB db; public SqlCeEventStore(EventStoreDB db) { this.db = db; } public void Dispose() { db.Dispose(); } } 

My problem is this: am I disposing EventStoreDB in the Dispose method of my class, given that it was passed to it in the constructor (and therefore, maybe it can be reused after my class is deleted)?

That is, if I dispose of it, I affirm that the correct use of my class is:

 using (var store = new SqlCeEventStore(new EventStoreDB)){ { //... } 

but I see that this alternative call is used:

 using (var db = new EventStoreDB()) using (var store = new SqlCeEventStore(db)) { //... } 

in this case, I should not dispose of EventStoreDB from the SqlCeEventStore class.

Are there any arguments for one style or another? I want to choose one and stick to it, and I would not flip a coin :)

+4
source share
5 answers

In general, there is no rule for this, but yes, I agree that since the object was created outside of your scope and transferred to you, you do not have it.

If you created it, then you should have all rights to do whatever you like (with documentation of expected behavior for callers)

This is a classic composition against aggregation .

+2
source

If EventStoreDB belongs to SqlEventStore (i.e., is part of its composition), it must be constructed or combined with the SqlEventStore class.

If it has use outside the scope of the SqlEventStore life cycle, it must be created and deleted by external code.

+1
source

There is no general rule, and IMHO should not be either. Different objects have different periods of life, and the most common guideline will be to ensure that the objects are managed sequentially in accordance with their lifespan, and that the life span is as short as possible.

You can try to use the following as a guide (but don't be afraid to stray when you need to): Dispose of the object in the same area as you select it. This guide is suitable for many scenarios, and this is exactly what simplifies the using statement.

If you have long-lived objects without an obvious burial point, do not worry. This is normal. However, ask yourself: do I really need this object to live as long as this happens? Is there any other way that I can simulate this in order to shorten the life? If you can find another way to shorten the life, this usually makes the object more manageable and should be preferred.

But then again, there is no "one true rule."

+1
source

You cannot choose one and stick to it. The user can always choose what he wants.

However, keep in mind that you are not responsible for the class of objects passed through the constructor.


Note

It's time to stupidly discuss, because if you want to impose initiation of the class using *new SqlCeEventStore(new EventStoreDB))* then why don't you remove this EventStoreDB parameter and instantiate the db variable inside your constructor.

Bypass

There is a workaround - check this out:

 public myClass { //do not make the constructor public //hide it private myClass(EventStoreDB db){ this.db = db; } //make a public constructor that will call the private one in the way you want public myClass(){ this(myClass(new EventStoreDB())); } } 
0
source

I would suggest that if it is possible to reasonably imagine situations in which the constructed object will be the last in the universe that is interested in the transferred object, as well as situations in which other things want to continue to use the passed In the object after the constructor is executed, it may be desirable to have a constructor parameter which indicates whether the new object should own the transferred object.

Please note that if the constructed object will own the passed object, it is important to make sure that the object will be deleted even if the constructor throws an exception. One way to do this is to wrap the constructor call in a routine that, in the finally block, will delete the passed object if the constructor did not complete successfully.

0
source

All Articles