在C#中将基类实例转换为派生类(向下转换)

假设我有两个类:

class Employee 

 class AdvancedEmployee:Employee 

我知道这样的事情是行不通的,因为我不能在C#上贬低:

 var employee = new Employee(); var advanced = employee as AdvancedEmployee; 

我的问题是:如何以有效的方式完成垂头丧气? 实际上我在AdvancedEmployee上有一个构造函数,它将Employee作为参数并使用它来注入其值,基本上是克隆。


更新

为了解决可能重复的数据,我改变了方法,现在AdvancedEmployee包含了一个员工而不是一个员工。 例:

 class Employee; class AdvancedEmployee { private employee public AdvancedEmployee(Employee employee){ this.employee = employee } } 

创建一个界面。 由于您无法修改Employee,因此请创建您拥有的适配器 :

 class EmployeeAdapter : IEmployee { private Employee emp; public EmployeeAdapter(Employee emp) { this.emp = emp; } public int SomeMethodInEmployee() { return emp.SomeMethodInEmployee(); } } class AdvancedEmployee : IEmployee { } 

它不能是演员 ,它实际上是不同类型之间的转换

我会添加一个ctor或静态成员函数,如AdvancedEmployee FromBase(Employee e) ,从给定的基类型构造派生类型。

创建新对象是最可读和最清晰的方式。 您还可以在Employee类中定义显式或隐式类型转换运算符。

 public static explicit operator AdvancedEmployee(Employee e) { return new AdvancedEmployee(e); } 

然后像这样使用它:

 var e = new Employee(); var ae = (AdvancedEmployee) e; 

这是我过去处理它的一种方式,我觉得它很酷……如果Employee和AdvancedEmployee中的所有数据元素都是Properties,那么你可以使用reflection将数据值从基类复制到派生类中。 然后,您可以使用派生类,就好像他最初以这种方式键入,而无需封装基类。

 public class Employee { public int ID { get; set; } public string Foo { get; set; } public void SomeMethod() { } } public class AdvancedEmployee : Employee { public string Bar { get; set; } public void SomeAdvMethod() { } } Employee emp = new Employee() { ID = 5, Foo = "Hello" }; // To create a AdvancedEmployee from emp AdvancedEmployee advEmp = new AdvancedEmployee() { Bar = "A prop not in Emp that might need a value" } foreach (var p in typeof(Employee).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.CanWrite)) typeof(AdvancedEmployee).GetProperty(p.Name).SetValue(advEmp, p.GetValue(emp)); 

as在C#中检查运行时类型一样 。 也就是说,如果被测试的对象确实不是AdvancedEmployee ,那么你就不会让它神奇地将Employee转换为AdvancedEmployee 。 因此,如果您需要AdvancedEmployee ,您需要以某种方式自己构建它。

根据您要实现的目标,有不同的方法。 也许您可以使用构造函数AdvancedEmployee(Employee proto) ,它将从proto复制所需的值? 或者您可能需要使用AdvancedEmployee包装现有Employee

请注意,您可能需要让存储旧员工的代码将其替换为新创建的AdvancedEmployee

一种方法(具有一些Java品味)可能是创建一个Employee工厂,如果需要,它将创建一个AdvancedEmployee 。 然后,您需要使所有代码使用工厂,而不是使用new创建Employee 。 但是,如果您仍需要更改运行时类型,则此方案无济于事。