委托构造函数调用

时间:2009-12-28 23:01:01

标签: c# constructor delegates nullreferenceexception

我遇到了一个容易解决的但是我年轻时没有遇到过的设计问题。

我有一个课程,在其他任何事情发生之前需要经过一些设置程序。

但是,在构造这个类的过程中,我在构造函数的参数中有一个可以传递的委托,以便用户可以将自己的信息添加到类中。

当调用它时,创建类的作用域仍然没有有效的实例,因此会发生null异常错误。

我该如何设计呢?我应该将“this”的实例传递给该代表吗?

在这里做出什么样的好决定?我有一个“StartServices()”方法,我可以很容易地调用委托,但我觉得它应该在构造函数中设计明智。

感谢您的建议!

5 个答案:

答案 0 :(得分:6)

听起来你想传递一个Action<T>(或类似的),这样无论在哪个阶段想要代表,它都可以调用theDelegate(this);例如:

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

然后obj将成为创建它的实例,它的优点是编译器生成的方法不需要任何状态/捕获(除非你自己需要)。

然而!我会谨慎地在构造函数中调用委托 ,因为virtual应该谨慎对待 - 在深层对象模型中,整个类可能无法完全创建触发您的中级构造函数(调用委托或重写方法),提供对处于不完整状态的对象的狡猾访问。

答案 1 :(得分:4)

考虑使用factory method

public class MyClass
{
    private MyClass() {}

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

然后像这样使用它:

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

您也可以选择工厂类:

var o = factory.CreateMyClass(...);

答案 2 :(得分:3)

我建议不要在构造函数中使用委托。委托可以轻松访问其他线程上的数据,从而导致几个非明显的副作用。在这种情况下,您应该拆分类创建和类初始化。

使用Factory pattern将帮助您清楚地分离对复杂对象创建的责任,但不能帮助您完成对象初始化。我确实考虑将行为注入构造函数中的反模式。

问题的解决方案可以将行为作为(对象)依赖关系注入定义良好的接口。您希望将代表传递给constroctur,这表明对我的担忧和违反SingelResponsibility原则的分歧很差。

答案 3 :(得分:2)

基本上,听起来你想要的代码根本不应该在构造函数中。构造函数是创建对象的原因。直到它退出对象不能保证“正常工作”。现在,可能工作,是的,你可以得到这个指针,但调用代码会期望它完全构建。因此从设计的角度来看,这不是一个好习惯。只需要在构造函数之后调用另一个方法(如果这有助于你的多态,则使用接口)。

答案 4 :(得分:0)

这种方法看起来很奇怪,代表们做了什么样的设置工作?

也许在构造函数结束时引发一个事件将是一个更标准的方法。