假设我有这样的课程:
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
,但我不完全确定这是最好的选择。
答案 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
。