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

Mik*_*fer 6 .net dependency-injection exception

假设我有这样一个类:

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

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

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

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

public IFormatter Formatter { get; set; }
public IParser Parsre { get; set; }
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

ale*_*exn 12

我会抛出一个InvalidOperationException.MSDN定义是:

方法调用对于对象的当前状态无效时引发的异常.

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

  • 乔恩·斯基特对此表示同意。我被卖了。(参见:http://stackoverflow.com/questions/1903105/which-exception-to- throw-when-a-method-try-to-use-a-field-that-c​​an-be-null)。 (2认同)

Mar*_*ann 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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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