【问题标题】:How to implement the copy method of the decorator of a generic class?如何实现泛型类的装饰器的复制方法?
【发布时间】:2012-11-12 13:41:30
【问题描述】:

假设您有一个通用接口,它定义了一个通用值和一个像这样的复制构造函数(替换 ICloneable):

// T: type of value to hold, TU: type of the class itself
interface ICopyable<T,TU> where TU: ICopyable<T,TU> {
    T Value { get; set; }
    TU Copy();
}

这可以通过这样的布尔值持有者来实现:

class BooleanHolder : ICopyable<Boolean, BooleanHolder> {
    public BooleanHolder Copy() { 
        return new BooleanHolder(){ Value = Value }; 
    }
}

现在问题来了:如何定义一个包含另一个 ICopyable 的装饰器类?我不工作的想法是:

class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> {
    public DecoratingHolder<T,TU> Copy {
        // won't compile as Value is of type T and not of type ICopyable<T,TU> 
        // as I expected - why is that?
        return new DecoratingHolder<T,TU>(){ Value = Value.Copy };
    }
}

请注意,我调用Copy 也是为了复制ICopyable&lt;T,TU&gt; 类型的值,这是为了确保深拷贝。

那么我必须改变什么才能使这个结构正常工作?

【问题讨论】:

    标签: c# generics copy decorator


    【解决方案1】:

    您可能只需要添加一个约束。您定义了 ICopyable&lt;T, TU&gt; where TU : ICopyable&lt;T, TU&gt;,但在您的 DecoratingHolder 中,您永远不会在 DecoratingHolder 上明确约束 TU

    更具体地说,我认为这是该行的这一部分:

    class DecoratingHolder<T,TU> : ***ICopyable<ICopyable<T,TU>***
    

    这是导致问题的原因。您正在定义 ICopyable&lt;T,TU&gt; 类型,但 TU 并未被限制为 ICopyable&lt;T, TU&gt;。 (也许可以从类声明/继承的其余部分推断,但编译器不能)一旦添加了约束,编译器知道 Value 是兼容的 ICopyable&lt;T,TU&gt; 类型。

    这对我来说编译得很好(必须用您提供的伪代码修复一些其他小问题):

    class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> 
        where TU : ICopyable<T,TU>
    {
        public ICopyable<T,TU> Value { get; set; }
    
        public DecoratingHolder<T,TU> Copy() {
            return new DecoratingHolder<T, TU>(){ Value = Value };
        }
    }
    

    编辑:回想起来,你甚至需要对ICopyable 的约束吗?似乎没有做太多,因为无论如何您已经普遍定义了传出类型。除非您在其他地方有代码取决于它出于某种原因返回 ICopyable&lt;T, TU&gt; 的事实(它本质上无论如何都会返回强类型的 TUBooleanHolderDecoratingHolder)然后考虑转储它。

    interface ICopyable<T,TU>
    {
        T Value { get; set; }
        TU Copy();
    }
    
    class BooleanHolder : ICopyable<Boolean, BooleanHolder> 
    {
        public bool Value { get; set; }
        public BooleanHolder Copy() { 
            return new BooleanHolder(){ Value = Value }; 
        }
    }
    
    class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> 
    {
        public ICopyable<T,TU> Value { get; set; }
    
        public DecoratingHolder<T,TU> Copy() {
            return new DecoratingHolder<T, TU>(){ Value = Value };
        }
    }
    

    编辑:从您需要深拷贝的评论中,保留约束(您将需要它们),并在 Value 上调用 Copy(抱歉,我一定错过了那个细节)

    class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> 
        where TU : ICopyable<T,TU>
    {
        public ICopyable<T,TU> Value { get; set; }
    
        public DecoratingHolder<T,TU> Copy() {
            return new DecoratingHolder<T, TU>(){ Value = Value.Copy() };
        }
    }
    

    任何给定类的Copy 方法应确保它们执行深层复制。 (我建议将 Copy 重命名为 DeepCopy 如果您的框架需要它们是深拷贝并且您不希望实现意外地做浅层)

    【讨论】:

    • @ChrisSinclair 啊,抱歉,我刚刚注意到我忘记提及实现深拷贝的必要性。你会调整你的答案吗
    • @Bastian 抱歉,我忽略了那个细节。我添加了另一个编辑。
    【解决方案2】:

    一个演员为我工作:

        public DecoratingHolder<T, TU> Copy()
        {
            return new DecoratingHolder<T, TU>() { Value = (ICopyable<T, TU>)Value.Copy() };
        }
    

    我猜在这种情况下,编译器并没有确定TUICopyable&lt;T, TU&gt; 是同一件事。

    【讨论】:

      猜你喜欢
      • 2019-02-03
      • 2021-12-21
      • 2017-08-12
      • 2012-02-09
      相关资源
      最近更新 更多