C# If.Create()可以';t实例化,它应该返回空对象、null还是抛出异常?

C# If.Create()可以';t实例化,它应该返回空对象、null还是抛出异常?,c#,exception-handling,instantiation,C#,Exception Handling,Instantiation,我希望能够用这种代码实例化应用程序中的任何对象: SmartForm smartForm = SmartForm.Create("id = 23"); Customer customer = Customer.Create("id = 222"); 我现在正在讨论如果该对象不存在,Create()应该返回什么 如果Create()返回一个空对象,那么这是一种“空模式”,我仍然可以在应用程序中传递该对象并调用其上的方法,这使得使用该模型编程变得方便和容易 如果Create()返回null,那么

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

SmartForm smartForm = SmartForm.Create("id = 23");
Customer customer = Customer.Create("id = 222");
我现在正在讨论如果该对象不存在,Create()应该返回什么

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

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

  • 如果Create()它可能会冒泡,这样您就可以更明确地处理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;
            }
        }
    }
}

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

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

当默认行为是创建实例时,然后异常行为是创建->异常失败

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

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


我会实现异常变量,但这取决于您需要的行为。

这取决于-如果它因为某些事情肯定是错误而失败,那么异常会使编程更容易-您不必围绕每个调用编写try/catch,只需让异常冒出来即可。将其与检查空/空返回值,然后引发异常进行比较

这听起来是使用
ArgumentException
,IMO的正确时机

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

您的示例代码调用了一个“try load from DB”方法,而Create约定看起来很像一个对象。为什么不分离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<SmartForm>.Find(1);
SmartForm otherEntity = ActiveRecordMediator<SmartForm>.FindFirst(/* criteria */);
smartformentity=ActiveRecordMediator.Find(1);
SmartForm otherEntity=ActiveRecordMediator.FindFirst(/*条件*/);

有许多其他方法可用于查找实例。我想你会发现ActiveRecord返回null,或者在集合的情况下是空集合,都是非常一致的,并且实现得很好。

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

是的,一路处理所有空值都会很乏味,好的一点是“id=23”在极少数情况下作为参数可能有意义,但它是一种巨大的代码气味。你不想像这样伪造关键字参数。最好执行SmartForm.Create(23)或SmartForm.Create(){Id=23};(对象初始值设定项)是的,但这里的目的是使查询实例化语法得以发展,因此在开发时可以说Create(“conferenceCode=mix09”)等。还有一个解析引擎可以管理这个字符串看到我关于管理这种复杂性的回答,你提出了正确的问题,但是你应该使用数据框架的强大功能进行初始化。我实际上制作了一个框架来实现这一点(PHP),并且它很容易使用,例如,你只需创建一个对象并删除它,两行搜索,它实际上没有创建任何对象,然后删除它不会做任何事情,而且一切都可以,显示一个对象也是如此,如果用户请求一个对象,并在应该显示的地方看到一个空白,那么很明显它不存在,这都使得使用该框架开发“如果这是一个正常的sc”非常快速+1