我正在尝试在抽象基类中实现ICloneable.Clone()
,以便子类不必担心它。
该类的一个基本职责是拥有一个内部Guid
属性,该属性应该传递给克隆 - 也就是说,它更像是一个"属性克隆"。这允许我克隆从存储库中获取的项目,更改其属性而不更改原始项目,然后以一种可以通过Id识别它的方式将更改的实例提交回存储库。
但我当前的实现面临一个问题:我无法创建实例来传递Id,因为该类是抽象的!
public abstract class RepoItem : ICloneable, IEquatable<RepoItem>
{
protected RepoItem()
{
Id = Guid.NewGuid();
}
private RepoItem(Guid id)
{
Id = id;
}
public Guid Id { get; private set; }
public object Clone()
{
return new RepoItem(Id); // cannot create instance of abstract class
}
public bool Equals(RepoItem other)
{
return other.Id == Id;
}
}
有没有办法克服这个问题?这是一个体面的设计吗?
答案 0 :(得分:3)
退后一步。 您根本不应该实现此接口,因此无论实现是在基类中还是在完全不同的地方。不要只是不去那里。
此界面自2003年以来已被弃用。请参阅:
Why should I implement ICloneable in c#?
了解详情。
答案 1 :(得分:0)
正如评论中已经解释的那样,你不能这样做......
最好的做法可能是使Clone
成为一个抽象方法(以确保所有派生类都可以使用克隆,但如果超过一个级别,则必须明确覆盖Clone
推导以及一个级别具有可以实例化的class
的更多。)。
之后,拥有一种复制构造函数将是最佳选择:
class RepoItem : ICloneable
{
public abstract void Clone();
protected RepoItem(RepoItem other) { Id = other.Id; }
}
class Derived1 : RepoItem
{
protected Derived1(Derived1 other) : base(other)
{
myField1 = other.myField1;
}
public virtual object Clone() { return new Derived1(this); }
private int myField1;
}
class Derived2 : Derived1
{
protected Derived2(Derived2 other) : base(other)
{
myField2 = other.myField2;
}
public override object Clone() { return new Derived2(this); }
private int myField2;
}
我不确定我是否正确virtual
和override
因为我很少写这样的代码。