将自定义ICloneable实现放在抽象基类中

时间:2016-10-03 18:11:10

标签: c# clone

我正在尝试在抽象基类中实现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;
    }
}

有没有办法克服这个问题?这是一个体面的设计吗?

2 个答案:

答案 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;
}

我不确定我是否正确virtualoverride因为我很少写这样的代码。