ケース1:すべてのBrush
派生クラスにはパブリックデフォルトコンストラクターがあり、すべてのプロパティにはパブリックセッターがあります。
この場合、1つの一般的な方法で十分です。
static TBrush Copy<TBrush>(this TBrush brush) where TBrush : Brush, new()
{
return new TBrush() // <- possible due to the `new()` constraint ^^^
{
TypeOfHair = brush.TypeOfHair,
NumberOfHairs = brush.NumberOfHairs,
…
};
}
ケース2:上記の前提条件の1つ以上が満たされていない。つまり、パブリックのデフォルトコンストラクタがないか、少なくとも1つのプロパティがパブリックに設定できません。
次のパターンを使用できます。
abstract class Brush
{
protected abstract Brush PrepareCopy();
// replacement for public default ctor; prepares a copy of the derived brush
// where all private members have been copied into the new, returned instance.
public Brush Copy()
{
// (1) let the derived class prepare a copy of itself with all inaccessible
// members copied:
Brush copy = PrepareCopy();
// (2) let's copy the remaining publicly settable properties:
copy.TypeOfHair = this.TypeOfHair;
copy.NumberOfHairs = this.NumberOfHairs;
return copy;
}
}
sealed class FooBrush : Brush
{
public FooBrush(int somethingPrivate)
{
this.somethingPrivate = somethingPrivate;
// might initialise other members here…
}
private readonly int somethingPrivate;
protected override Brush PrepareCopy()
{
return new FooBrush(somethingPrivate);
}
}