为什么我的克隆代码没有编译?

时间:2013-06-13 14:41:44

标签: c# interface clone

我有这个简单的克隆界面,我想使用它。它看起来应该编译,但事实并非如此。我收到一条消息,说我的BObject课程没有实现DeepClone()。我不理解这一点,因为我有DeepClone()方法而我的BObject实现了 IObject

interface IDeepCloneable<T>
{
    T DeepClone();
}

interface IObject : IDeepCloneable<IObject>
{
    string Name { get; }
    double Sales { get; }
}

//'BObject' does not implement interface member
//  'IDeepCloneable<IObject>.DeepClone()'
class BObject : IObject
{
    public string Name { get; set; }
    public double Sales { get; set; }

    public BObject DeepClone()
    {
        return new BObject() { Name = this.Name, Sales = this.Sales };
    }
}

我声明我的界面错了吗?


或者DeepClone实施?我可以使用这段代码:

public IObject DeepClone() //returns an IObject instead of a BObject
{
    return new BObject() { Name = this.Name, Sales = this.Sales };
}

我遇到的问题是没有检查BObject.DeepClone()方法返回BObject的结果。我可以有一个看起来像这样的课:

class BObjectImposter : IObject
{
    public string Name { get; set; }
    public double Sales { get; set; }

    public IObject DeepClone()
    {
        //returns a BObject instead of a BObjectImposter
        return new BObject() { Name = this.Name, Sales = this.Sales };
    }
}

使用这个课,我可以这样写:

BObjectImposter objImp = new BObjectImposter();
IObject copy = objImp.DeepClone();

我可能希望copyBObjectImposter的实现,但它实际上是一个不相关的类BObject的实现,它恰好也实现了IObject。我理解接口的意义在于我使用哪种实现并不重要,但这对我来说似乎不是好的代码。也许在BObjectImposter实现的某个地方,我希望DeepClone()返回一个BObjectImposter对象。此外,IObject的一个实现不应该依赖于IObject的另一个实现。


也许我可以使IObject成为一个抽象类并在那里声明DeepClone()。如果我有一个实现(称之为ObjectA),我需要在构造函数中设置Name之前设置Sales,以及另一个实现(调用它{{}},这似乎可能会破坏我的设计{1}})我需要在构造函数中设置ObjectB之前设置Sales

2 个答案:

答案 0 :(得分:5)

正如您在问题中暗示的那样,IObject实现了IDeepClonable&lt; IObject &gt;,因此其DeepClone()方法必须返回IObject

您需要一直使用CRTP

interface IObject<T> : IDeepCloneable<T> where T : IObject<T>
class BObject : IObject<BObject>

(您还应该将where T : IDeepCloneable<T>添加到IDeepCloneable

答案 1 :(得分:1)

因为IObject继承IDeepCloneable<IObject>所以DeepClone将返回IObject。以下应该有效:

    interface IDeepCloneable<T>
{
    T DeepClone();
}

interface IObject<T> : IDeepCloneable<T>
{
    string Name { get; }
    double Sales { get; }
}

//'BObject' does not implement interface member
//  'IDeepCloneable<IObject>.DeepClone()'
class BObject : IObject<BObject>
{
    public string Name { get; set; }
    public double Sales { get; set; }

    public BObject DeepClone()
    {
        return new BObject() { Name = this.Name, Sales = this.Sales };
    }
}