C# 当工厂方法返回null时,我应该抛出什么异常?
考虑一个我可以控制也可以不控制的工厂方法,作为C# 当工厂方法返回null时,我应该抛出什么异常?,c#,.net,C#,.net,考虑一个我可以控制也可以不控制的工厂方法,作为Func传递给另一个类: //this.FactoryMethod是传递到此类的外部依赖项 //通过构造函数或属性注入,假定它不是null //但不能保证它将返回非空引用。 功能因子法; 公共IModel GetPopulatedModel(int状态,FileInfo someFile) { //为简洁起见,省略了参数验证。。。 //此操作可能返回null。 var model=this.FactoryMethod() if(mode
Func
传递给另一个类:
//this.FactoryMethod是传递到此类的外部依赖项
//通过构造函数或属性注入,假定它不是null
//但不能保证它将返回非空引用。
功能因子法;
公共IModel GetPopulatedModel(int状态,FileInfo someFile)
{
//为简洁起见,省略了参数验证。。。
//此操作可能返回null。
var model=this.FactoryMethod()
if(model==null)
{
抛出新的SomeException(“工厂方法无法生成值”);
}
//此时可以安全地分配给属性。
模型。优先级=状态;
model.File=someFile;
收益模型;
}
我想抛出一些指示操作失败的东西
ArgumentNullException
会产生误导,因为参数没有任何错误:
当一个空引用(在Visual Studio中为Nothing)时引发的异常
Basic)传递给不接受其为有效
争论
InvalidOperationException
似乎不太恰当:
当方法调用对的无效时引发的异常
对象的当前状态
认为将局部变量作为代码的一部分似乎很奇怪,对象的当前状态< /代码> < /P>
抛出什么样的异常比较好?我很惊讶
系统中没有操作失败异常
。我应该编写自己的异常,还是有一个好的异常?如果您觉得可用的异常不充分,您可以随时创建自己的异常
更新
尽管如此,我还是同意@TomTom和@dtb关于可能存在的选项的看法。尤其是NotImplementedException
,因为工厂确实没有实现我会创建自己的异常,称为
FactoryNullException
然后,您甚至可以创建所需的默认消息,例如示例中的消息
Factory method failed to produce a value.
无效操作例外
局部变量是根据定义定义对象状态的变量。没什么不好的。必须设置factory方法,否则无法创建对象。InvalidOperation-工厂当时无法创建对象,因为工厂的内部状态不正确。可能
NullReferenceException
是您想要的。来自.NET Framework的两个示例:
- 如果返回null,则抛出
无效操作异常类
当方法调用对于对象的当前状态无效时引发的异常
- 如果返回null,则抛出
未实现异常类
当请求的方法或操作未实现时引发的异常
CloneCore本质上是当前对象克隆的工厂方法
我会使用NotImplementedException,因为factory方法不会实现它所请求的内容。我不确定这是否就是您在这里实现的factory模式。但要回答您的问题,只需做如下自定义例外:
public class FactoryNullException : Exception
{
public FactoryNullException() : base("Factory was null")
{
}
}
为什么不使用InvalidOperationException(),因为如果该方法失败,您就无法控制所使用的方法,这意味着该方法无效。另一个选项:不要抛出异常。在实际应用程序中,该方法是从try/catch块中调用的,该异常将被捕获并记录。在这种情况下,抛出异常没有任何好处
因此,我没有抛出异常,而是记录消息并返回null。将其转换为示例代码如下所示:
// this.FactoryMethod is an external dependency passed into this class
// through constructor or property injection assume that it is not null
// but there is no guarantee that it will return a non-null reference.
Func<IModel> FactoryMethod;
public IModel GetPopulatedModel(int state, FileInfo someFile)
{
// Argument validation omitted for brevity...
// This operation could return null.
var model = this.FactoryMethod()
if (model == null)
{
this.Logger.Write("Factory method failed to produce a value.");
return null;
}
// Safe to assign to properties at this point.
model.Priority = state;
model.File = someFile;
return model;
}
//this.FactoryMethod是传递到此类的外部依赖项
//通过构造函数或属性注入,假定它不是null
//但不能保证它将返回非空引用。
功能因子法;
公共IModel GetPopulatedModel(int状态,FileInfo someFile)
{
//为简洁起见,省略了参数验证。。。
//此操作可能返回null。
var model=this.FactoryMethod()
if(model==null)
{
this.Logger.Write(“工厂方法无法生成值”);
返回null;
}
//此时可以安全地分配给属性。
模型。优先级=状态;
model.File=someFile;
收益模型;
}
如果抛出异常是必需的/有用的,我会选择NotImplementedException
,但在这种情况下,不抛出异常更有意义。NotImplementedException肯定不是正确的选择,而且它几乎不应该被生产代码抛出
在这个场景中抛出什么的最重要标准是什么对异常的消费者最有用。如果您期望调用代码对该异常的反应可能与对任意异常的反应不同,那么异常类型非常重要。另一方面,对于这样的异常,调用代码所能做的唯一一件事就是记录它,它的消息非常重要,它的类型也不那么重要。在后一种情况下,带有显式消息的InvalidOperationException可能非常合适
同样值得考虑的是,从工厂方法返回空值是否应该被视为违反其合同。在这种情况下,您希望抛出异常这一事实表明它可能应该抛出异常,在这种情况下,您可能希望稍微更改设计,以便注入接口实例,而不是Func
。这将允许您在接口方法上定义一个文档化的契约,指定它永远不会返回null,并且
// this.FactoryMethod is an external dependency passed into this class
// through constructor or property injection assume that it is not null
// but there is no guarantee that it will return a non-null reference.
Func<IModel> FactoryMethod;
public IModel GetPopulatedModel(int state, FileInfo someFile)
{
// Argument validation omitted for brevity...
// This operation could return null.
var model = this.FactoryMethod()
if (model == null)
{
this.Logger.Write("Factory method failed to produce a value.");
return null;
}
// Safe to assign to properties at this point.
model.Priority = state;
model.File = someFile;
return model;
}