代码之家  ›  专栏  ›  技术社区  ›  Edward Tanguay

如果.Create()无法实例化,它应该返回空对象、null还是引发异常?

  •  3
  • Edward Tanguay  · 技术社区  · 16 年前

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

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

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

    • 无效的

    • 如果创建() 抛出异常 ,它基本上与返回null相同,但通过让您为每个实例化创建try、next、finally块,编程变得更加繁琐,但是您可以抛出各种类型的异常(使用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;
                }
            }
        }
    }
    
    6 回复  |  直到 16 年前
        1
  •  6
  •   Jon Skeet    16 年前

    这取决于-如果它失败是因为某些事情肯定是错误的,那么一个异常会导致编程失败 更容易的 -你不会在每次调用时都写一个try/catch,你只是让异常冒出来。将其与检查空/空返回值和 然后 正在引发异常。

    这听起来是正确的使用时间 ArgumentException ,国际海事组织。

    如果您发现自己正在创建try/catch“bloat”,请看看为什么您真的需要捕获异常,而不是让它们冒泡。

        2
  •  2
  •   Jon B    16 年前

    如果它返回一个空白对象,那么您将继续假设它是有效的——或者必须做一些复杂的测试来查看它是否为空白。如果它返回null,您将始终必须检查null(也许这很好)。我更希望它抛出一个异常——假设您的代码设计为不应该发生这种情况。如果这是一个正常的场景,那么null可能是一个更好的选择。

        3
  •  2
  •   tanascius    16 年前

    您将如何处理空对象?你说你仍然可以传递它-这真的有意义吗?当您调用这些方法时,它们会做什么?

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

        4
  •  1
  •   Anthony Mastrean PavanDevarakonda    16 年前

    您的示例代码调用了一个“try load from DB”方法,Create约定看起来很像 Castle ActiveRecord

    [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<SmartForm>.Find(1);
    SmartForm otherEntity = ActiveRecordMediator<SmartForm>.FindFirst(/* criteria */);
    

    有许多其他方法可用于查找实例。我想你会发现ActiveRecord defaults regarding throwing exceptions

        5
  •  0
  •   Mitch Wheat    16 年前

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

        6
  •  0
  •   supercat    14 年前

    如果可以预见创建可能会失败,但许多应用程序代码预期它会工作,那么您确实应该实现创建方法的两个版本,其中一个版本应该成功或引发异常,另一个版本应该通过引发异常以外的其他方式指示预期的失败,并且仅对调用方可能没有预料到的失败(例如cpuisonfierexception)抛出异常。执行此操作的常见模式是让TryCreate方法返回指示成功的布尔值,将创建的参数存储到by ref参数。我真的不喜欢这种模式,因为它只提供了一个pass-fail状态(也就是说,没有关于失败原因的任何信息),没有任何其他指示方法。我认为最好让一个“try”函数返回newthing或null,但要有一个by-ref参数指示失败的原因。请注意,这种方法可以更好地使用隐式类型(例如C#中的“var”关键字)。