如何中止对象初始化?

qua*_*els 7 c# oop

我正在写一个必须始终具有某些值的对象.最值得注意的是,它必须始终具有Name财产价值.

public class User
{
    public string Name { get; set; }

    public User(string name)
    {
        Name = name;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我需要在这个类中实现一些业务规则.其中之一是该Name属性必须是唯一的名称.所以,我认为这个对象的初始化器看起来像这样:

    public User(string name, IQueryable<User> allUsers)
    {
        var matches = allUsers.Where(q => q.Name == name).ToList();
        if(matches.Any())
        {
            // abort object initialization
        }
        Name = name;
    }
Run Code Online (Sandbox Code Playgroud)

但我不确定如何中止对象初始化.事实上,甚至可能吗?

有没有办法中止对象初始化(即:将对象设置为null)还是有更好的方法来实现它?

jas*_*son 6

好吧,你只是抛出异常.但我不喜欢这种处理这个问题的方式.相反,您应该通过服务创建用户,并让服务检查名称是否有效.


Dav*_*son 3

通过在构造函数中抛出异常来中止对象的初始化,建议拒绝无效输入。

public class User
{
    public User(String name) {
        if (String.IsNullOrWhiteSpace(name)) {
            if (name == null) {
                throw new System.ArgumentNullException("Cannot be null.", "name");
            }
            else {
                throw new System.ArgumentException("Cannot be empty.", "name");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您希望在构造函数中定义的业务逻辑不适合那里。构造函数应该是轻量级的,并且只是实例化。对于构造函数来说,查询某些数据源的成本太高。因此,您应该使用工厂模式。使用工厂模式,调用者可能期望对象创建涉及一些繁重的工作。

public class User
{
    private User(String name) {
        if (String.IsNullOrWhiteSpace(name)) {
            if (name == null) {
                throw new System.ArgumentNullException("Cannot be null.", "name");
            }
            else {
                throw new System.ArgumentException("Cannot be empty.", "name");
            }
        }
    }

    public static User CreateUser(String name) {
        User user = new User(name); // Lightweight instantiation, basic validation

        var matches = allUsers.Where(q => q.Name == name).ToList();

        if(matches.Any())           
        {           
            throw new System.ArgumentException("User with the specified name already exists.", "name");         
        }     

        Name = name;
    }

    public String Name {
        get;
        private set; // Optionally public if needed
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以看到工厂模式更适合,并且因为它是一种方法,调用者可能期望通过调用它来执行一些工作。而对于构造函数,人们会期望它是轻量级的。

如果您想采用构造函数路线,那么您可能需要尝试一些其他方法来强制执行业务规则,例如尝试实际插入数据源时。

public class User
{
    public User(String name) {
        if (String.IsNullOrWhiteSpace(name)) {
            if (name == null) {
                throw new System.ArgumentNullException("Cannot be null.", "name");
            }
            else {
                throw new System.ArgumentException("Cannot be empty.", "name");
            }
        }
    }
}

public class SomeDataSource {
    public void AddUser(User user) {
        // Do your business validation here, and either throw or possibly return a value
        // If business rules pass, then add the user
        Users.Add(user);
    }
}
Run Code Online (Sandbox Code Playgroud)