我试图根据输入创建子类的新实例。为此,我使用了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;
}
}
寻找解决这个问题的最佳解决方案。
答案 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();
}
请注意,您需要一个默认分支,否则编译器会在您尝试使用它时抱怨用户未正确分配(因为理论上有一个代码路径没有设置它)。