.NET:未设置必需属性时抛出哪个异常?

时间:2011-03-05 19:51:24

标签: .net exception dependency-injection

假设我有这样的课程:

public class Foo
{
    public Bar RequiredProperty { get; set;}

    public void Baz()
    {
        if (this.RequiredProperty == null)
        {
            // Which exception should I throw?
        }
    }
}

我的解决方案有一个专门设计用于重用的类,而不必一遍又一遍地向Bar方法传递大量参数。那么,当Bar未初始化为非空值时,我应该扔什么?

更多信息 我基本上是在编写自己的代码解析器和格式化程序。称之为对象课程。其中一个类是HtmlCodeFormatter,它具有以下属性(以表示依赖注入):

public IFormatter Formatter { get; set; }
public IParser Parsre { get; set; }

这允许我编写任意数量的特定于语言的解析器和格式化程序。例如,我有一个CSharpParser和一个JavascriptParser。我也有一个HtmlCodeFormatter,并且计划另一个(可疑的实用程序)。

我的想法是你可以使用对象初始化器来实例化HtmlFormatter,如下所示:

var formatter = new HtmlCodeFormatter()
    {
        Parser = new CSharpParser();
        Formatter = new HtmlCodeFormatter();
    };
formatter.Format("Console.WriteLine(\"Hello, world!\"));

当调用HtmlCodeFormatter.Format时,它需要能够验证是否已提供解析器和格式化程序。真的,这没问题,但我有点不知道抛出哪个异常。我倾向于InvalidOperationException,但我不完全确定这是最好的选择。

3 个答案:

答案 0 :(得分:12)

我会抛出InvalidOperationException。 MSDN定义是:

  

a时抛出的异常   方法调用无效   对象的当前状态。

但是,我建议使用构造函数注入而不是setter注入。这可确保您拥有有效的解析器和格式化程序。如果在构造函数中传递null,则抛出ArgumentNullException

答案 1 :(得分:7)

通过使用 Propery Injection ,您隐含地告诉编译器,其他开发人员以及DI容器依赖项是可选的。这是因为没有人强迫您分配属性值

如果确实需要依赖关系,则应重构为构造函数注入。这将有效地产生所需的依赖性:

public class Foo
{
    private readonly Bar bar;

    public Foo(Bar bar)
    {
        if (bar == null)
        {
            throw new ArgumentNullException("bar");
        }

        this.bar = bar;
    }

    public Bar RequiredProperty
    {
        get { return this.bar; }
    }

    public void Baz()
    {
        // this.bar is now GUARANTEED to be initialized,
        // so no checks are required
    }
}

请注意,构造函数Guard Clause(抛出ArgumentNullException)有效地保护了类的不变量readonly关键字进一步强化了这一点。

使用类'不变量的依赖部分,你不再有任何时间耦合,你现在可以实现所有成员而不用担心是否已经分配了依赖。

答案 2 :(得分:1)

你可以抛出NotInitializedException