请考虑以下类定义:
class A
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
class B : A // note that B is a subclass of A
{
// B has only one further property
public int OneMoreProperty { get; set; }
}
给定一个A
的实例,我需要创建一个具有相同值的B
实例。有没有比复制每个属性更好的方法呢?有机会利用B
是A
的子类这一事实吗?这是我目前拥有的,在我看来非常不方便且容易出错:
// Create instance of A
A instanceA = new A();
instanceA.Property1 = 1;
instanceA.Property2 = 2;
// Create instance of B with same
// values as the instance of A
B instanceB = new B();
instanceB.Property1 = instanceA.Property1;
instanceB.Property2 = instanceA.Property2;
instanceB.OneMoreProperty = 5;
正如@Jamiec所提到的,这里的继承关系可能通过组合更好地建模,但如果B
语义上是一个A
,一种方法是添加一个"复制构造函数":
class A
{
public int Property1 { get; set; }
public int Property2 { get; set; }
public A() { }
public A(A other)
{
Property1 = other.Property1;
Property2 = other.Property2;
}
}
class B : A
{
public int OneMoreProperty { get; set; }
public B() { }
public B(A other) : base(other) { }
}
然后,当您创建B
实例时:
B instanceB = new B(instanceA);
instanceB.OneMoreProperty = 5;
您已经非常清楚地说明了为什么出于"重用"属性的目的进行继承通常是错误的选择。
继承意味着一种is-a
关系,但你在这里建模的几乎可以肯定是A和B之间的has-a
关系。因此,B
应该只保存 A 的一个实例,而不需要将值从 A 复制到 B。
class A
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
class B
{
public A A{ get; set; }
public int OneMoreProperty { get; set; }
}
然后
// Create instance of A
A instanceA = new A();
instanceA.Property1 = 1;
instanceA.Property2 = 2;
// Create instance of B with same
// values as the instance of A
B instanceB = new B();
instanceB.A = instanceA;
instanceB.OneMoreProperty = 5;
这显然是过度简化的,你可能有一个需要A
的构造函数,你可以引入接口,这样你就可以使A
和B
以某种对你的领域有意义的共享方式运行。
您还应该考虑对象的不可变性,因为对上述示例中A
实例的更改将影响B
持有的引用。
我知道你到底是什么意思,有时有些类我们不能强制转换,因为多了一个属性。这可以使用反射来实现:
static Tout CopyProps<Tin, Tout>(Tin input) where Tout: Tin, new()
{
var result = new Tout();
foreach (var prop in typeof(Tin).GetProperties())
prop.SetValue(result, prop.GetValue(input));
return result;
}
用法是:
var a = new A{...}
var b = CopyProps<A,B>(a);