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

时间:2012-04-16 10:53:50

标签: c# downcast

假设我有两个类:

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

  }           

}

5 个答案:

答案 0 :(得分:5)

创建一个界面。由于您无法修改员工,请创建您拥有的adapter

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

class AdvancedEmployee : IEmployee { } 

答案 1 :(得分:4)

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

我会将一个ctor或静态成员函数(如AdvancedEmployee FromBase(Employee e))添加到构造派生类型中。

答案 2 :(得分:2)

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

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

然后像这样使用它:

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

答案 3 :(得分:2)

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

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));

答案 4 :(得分:1)

C#中的

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

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

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

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