如果.Create()无法实例化,它应该返回空对象,null还是抛出exception?

我希望能够使用这种代码实例化我的应用程序中的任何对象:

SmartForm smartForm = SmartForm.Create("id = 23"); Customer customer = Customer.Create("id = 222"); 

我现在正在讨论如果该对象不存在,Create()应该返回什么。

  • 如果Create()返回一个空对象 ,那么这是一种“空模式”,我仍然可以在我的应用程序周围传递该对象并在其上调用方法,这使得使用此模型进行编程变得方便和容易

  • 如果Create()返回null ,那么我需要在每次实例化后检查对象是否等于null,这使得编程更乏味但更明确。 这样做的一个问题是,如果你忘记检查null,你的应用程序可能会工作很长时间而你不知道你没有检查null,然后突然中断

  • 如果Create() 抛出exception ,它基本上与返回null相同,但是通过让你为每个实例化创建一个try,next,finally块,使编程更加繁琐,但你可以抛出各种类型的exception(你可以’ t使用null解决方案)可能会冒泡,以便您可以更明确地处理UI上的深层错误,所以我认为这是最强大的解决方案,尽管会产生try / catch代码膨胀

所以它似乎是轻盈/稳健性的折衷有没有人有任何经验可以根据这个决定在这些方面做出决定?

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestFactory234.Models { public class SmartForm : Item { public string IdCode { get; set; } public string Title { get; set; } public string Description { get; set; } public int LabelWidth { get; set; } public SmartForm() { } private SmartForm(string loadCode) { _loadCode = loadCode; TryToInstantiateFromDatabase(); } public static SmartForm Create(string loadCode) { SmartForm smartForm = new SmartForm(loadCode); if (!smartForm.IsEmpty()) { return smartForm; } else { return null; } } } } 

这取决于 – 如果它失败是因为某些东西肯定是错误的,那么exception会使编程变得更容易 – 你不会在每次调用时编写try / catch,只是让exception冒泡。 将其与检查null /空白返回值进行比较, 然后抛出exception。

这听起来像是使用ArgumentException ,IMO的正确时间。

如果你发现自己创建了try / catch“膨胀”,那么看看为什么你真的需要捕获exception而不是让它们冒泡。

如果它返回一个空白对象,那么你将继续假设它是有效的 – 或者必须进行某种精心测试以确定它是否为空白。 如果它返回null,你将始终必须检查null(也许那很好)。 我希望它抛出exception – 假设您的代码是为了不应该发生而设计的。 如果这是正常情况,那么null可能是更好的选择。

当默认行为是创建实例时,exception行为将失败,创建 – >exception

你会用EmptyObject做什么? 你说你仍然可以传递它 – 这真的有意义吗? 当你打电话给他们时,这些方法会做什么?

也许你应该实现第二个TryCreate()方法。

我实现了Exception-variant,但它取决于你需要的行为。

您的示例代码调用“从DB尝试加载”方法,并且Create约定看起来很像Castle ActiveRecord对象。 为什么不分离Get / Create数据库操作,允许框架完成工作并依赖于它们的约定?

 [ActiveRecord("Forms")] public class SmartForm : Item { [PrimaryKey("Id")] public string IdCode { get; set; } [Property] public string Title { get; set; } [Property] public string Description { get; set; } [Property] public int LabelWidth { get; set; } } 

你得到/创建这样的实例

 SmartForm entity = ActiveRecordMediator.Find(1); SmartForm otherEntity = ActiveRecordMediator.FindFirst(/* criteria */); 

还有很多其他方法可用于查找实例。 我想你会发现ActiveRecord 关于 抛出 exception ,返回null的默认值,或者在集合的情况下,一个空集合的默认值非常一致且实现得很好。

如果要创建表单工厂,则最好传递枚举而不是字符串(当然,除非代表插件体系结构)。

如果可以预见创建可能会失败,但很多应用程序代码会期望它能够正常工作,那么你真的应该实现两个版本的创建方法,其中一个应该成功或抛出exception,另一个应该是应该通过除抛出exception之外的某些方式指示预期的失败,并且仅针对调用者可能没有预料到的失败抛出exception(例如CpuIsOnFireException)。 执行此操作的常见模式是让TryCreate方法返回指示成功的布尔值,将创建的参数存储到by-ref参数。 我真的不喜欢这种模式,因为除了传递失败状态之外,它没有提供任何指示任何东西的方法(即没有关于它失败的原因)。 我认为让“try”函数返回new或null是更好的,但是有一个by-ref参数指示失败的原因。 请注意,这种方法可以更好地使用隐式类型(例如C#中的“var”关键字)。