在 C# 中将基实例强制转换为派生类(向下转换)
本文关键字:转换 派生 实例 | 更新日期: 2023-09-27 18:31:11
>假设我有两个类:
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
}
}
它不可能是演员表,它实际上是不同类型之间的转换。
我会添加一个像 AdvancedEmployee FromBase(Employee e)
这样的 ctor 或静态成员函数,以从给定的基类型构造派生类型。
创建一个接口。由于您无法修改员工,因此请创建您拥有的适配器:
class EmployeeAdapter : IEmployee
{
private Employee emp;
public EmployeeAdapter(Employee emp) { this.emp = emp; }
public int SomeMethodInEmployee() { return emp.SomeMethodInEmployee(); }
}
class AdvancedEmployee : IEmployee { }
过去处理它的一种方式,我认为有点酷......如果 Employee 和 AdvancedEmployee 中的所有数据元素都是属性,则可以使用反射将数据值从基类复制到派生类中。 然后,您可以使用派生类,就好像他最初是以这种方式键入的一样,而不必封装基类。
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));
创建新对象是最易读和最清晰的方法。还可以在 Employee 类中定义显式或隐式类型转换运算符。
public static explicit operator AdvancedEmployee(Employee e)
{
return new AdvancedEmployee(e);
}
然后像这样使用它:
var e = new Employee();
var ae = (AdvancedEmployee) e;
C# 中的as
检查运行时类型。也就是说,如果被测试的对象确实不是AdvancedEmployee
,您将不会使其神奇地将Employee
转换为AdvancedEmployee
。所以如果你需要一个 AdvancedEmployee
,你需要以某种方式自己构建它。
根据您要实现的目标,有不同的方法。也许你可以使用构造函数AdvancedEmployee(Employee proto)
,它将从proto
复制所需的值?或者,也许您需要用AdvancedEmployee
包装现有Employee
.
请注意,您可能需要让存储旧员工的代码将其替换为新创建的AdvancedEmployee
。
一种方法(带有一些Java风格)可能是创建一个Employee
工厂,如果需要,它将创建一个AdvancedEmployee
。然后,您需要使所有代码都使用工厂,而不是使用new
创建Employee
。但是,如果您无论如何都需要更改运行时类型,则此方案将无济于事。