views:

234

answers:

5

I've run into an easily solved but a design problem I've not encountered in my young life yet.

I have a class that needs to go through a few setup procedures before anything else happens.

However, during the construction of this class, I have in the constructor's parameters a delegate that can be passed so that the user can add their own information to the class.

When this is called however the scope that is creating the class still doesn't have a valid instance and therefore a null exception error occurs.

How do I design around this? Should I pass an instance of "this" to that delegate?

What is a good decision to make here? I have a "StartServices()" method where I could easily put the call to the delegate but I feel design wise it should be in the constructor.

Thanks for the advice!

+3  A: 

It sounds like you want to pass an Action<T> (or similar), so that at whichever point the class wants the delegate, it can call theDelegate(this); for example:

var instance = new SomeType(..., obj => { /* extra code invovling obj */ });

Then obj will be the instance when it is created, and it has the advantage that the compiler-generated method doesn't require any state / capture (unless you need that yourself).

However! I would cautious of calling a delegate inside a constructor, for the same reason that virtual should be treated with caution - in a deep object model the entire class may not be fully created at the point your mid-level constructor (that invokes the delegate or overridden method) fires, providing dodgy access to an object in an incomplete state.

Marc Gravell
The delegate can only access public methods on the class. Thanks for the info!
bobber205
+3  A: 

Consider using a factory method:

public class MyClass
{
    private MyClass() {}

    public static MyClass Create(delegate d ...)
    {
        var instance = new MyClass();
        d.(instance);
        return instance;
    }
}

then use it like this:

var o = MyClass.Create(...);

You could also go with a factory class:

var o = factory.CreateMyClass(...);
Michael Valenty
+2  A: 

Basically, it sounds like the code you want shouldn't be in the constructor at all. The constructor is what creates the object. Until it exits the object isn't guaranteed to "work properly". Now, it may work and yes, you can get the this pointer, but calling code would expect it to be fully constructed. So from a design point of view this is not a good practice. Just have another method that is called after the constructor (with an interface if that would help your polymorphism).

Evgeny
A: 

That approach seems strange, what kind of setup work is done via the delegates?

Perhaps raising an event at the end of the constructor would be a bit more standard method.

STW
+2  A: 

I recommend against using a delegate inside a constructor. The delegate could easily access data on other threads, causing several non-obvious side effects. You should split class creation and class initialization in this case.

Using the Factory pattern will help you cleanly seperate responsibility for complex object creation, but no object initialization. I do consider injecting behaviour into a constructor an anti-pattern.

A Solution to your problem can be injecting behaviour as (object-) dependencies with well-defined interfaces. Your wish to pass a delegate into the constroctur is a sign of a poor seperation of concerns and violation of the SingelResponsibilityPrinciple to me.

Johannes Rudolph