C#在switch语句中定义子类

时间:2017-05-19 08:24:48

标签: c# entity-framework asp.net-mvc-5

我试图根据输入创建子类的新实例。为此,我使用了switch语句。

[HttpPost]
public ActionResult Register(RegisterViewModel model)
{
    var user = new User();

    switch (model.UserType)
    {
        case UserType.Normal:
            user = (NormalUser) user;
            // NormalUser properties cannot be defined here
            break;
        case UserType.Vip:
            user = (VipUser) user;
            // VipUser properties cannot be defined here
            break;
    }
}

寻找解决这个问题的最佳解决方案。

2 个答案:

答案 0 :(得分:5)

使用new User()时,您正在创建此类的新实例,该实例不了解其任何子类。因此,任何一个都失败了。

问题是程序无法知道在执行强制转换时如何设置NormalUser中定义的成员而不是基类中定义的成员。因此,假设您的基类有成员Name和Àdressand your NormalUser has an年龄-property in addition to those two ones. What would you expect would the年龄be when casting your existing用户to NormalUser . Your program can´t know how to set Age`。

你必须为此创建一个拷贝构造函数,或者在切换之前不要实例化变量:

User user;

switch (model.UserType)
{
    case UserType.Normal:
        user = new NormalUser();
        break;
    case UserType.Vip:
        user = new VipUser()
        break;
}

这遵循工厂模式,因此此方法的用户可以使用它来创建给定类型的实例,而不依赖于该类型,从而减少客户端代码与工厂中创建的实际类型的耦合。

您还需要一些default - 切换以让编译器知道如果您的条件都没有通过该怎么办 - 即使在您的方案中不可能这样做。例如,您可能会在这种情况下抛出异常。

复制构造函数的选项来自:

class NormalUser
{
    public NormalUser(User user, int age)
    {
        this.Name = user.name;
        this.Adress = user.Adress;
        // further properties defined in the base-class

       this.Age = age
       // further properties defined in NormalUser
    }
}

如您所见,这是对财产的大量复制。特别是第一个选项更适合你的风暴。

答案 1 :(得分:3)

您不是在创建子类型的新版本,而只是尝试转换现有对象。请尝试以下方法。

User user;

switch (model.UserType)
{
    case UserType.Normal:
        var newUser =  new NormalUser();
        //set properties...
        user = newUser;
        break;
    case UserType.Vip:
        var newuser =  new VipUser();
        //set properties...
        user = newUser;
        break;
    default:
        throw new Exception();
}

请注意,您需要一个默认分支,否则编译器会在您尝试使用它时抱怨用户未正确分配(因为理论上有一个代码路径没有设置它)。