简体   繁体   English

如何实现泛型类装饰器的复制方法?

[英]How to implement the copy method of the decorator of a generic class?

Imagine you have a generic interface that defines a generic value and a copy constructor like this (replacing ICloneable): 想象一下,你有一个定义通用值的泛型接口和这样的复制构造函数(替换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();
}

This could be implemented by a boolean value holder like this: 这可以通过像这样的布尔值持有者来实现:

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

Now comes the question: How would you define a decorator class that holds another ICopyable? 现在问题是:你如何定义一个装有另一个ICopyable的装饰器类? My not working idea was: 我不懂的想法是:

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

Note that I called Copy to also have the value of type ICopyable<T,TU> copied, this is on purpose to ensure deep copies. 请注意,我调用Copy to也具有Copy类型ICopyable<T,TU>的值,这是为了确保深层复制。

So what do I have to change to make this structure work? 那么我需要改变什么来使这个结构工作?

You might just need to add a constraint. 您可能只需要添加约束。 You define that ICopyable<T, TU> where TU : ICopyable<T, TU> but in your DecoratingHolder , you never explicitly constraint TU as such on DecoratingHolder . 你定义了ICopyable<T, TU> where TU : ICopyable<T, TU>但在你的DecoratingHolder ,你从来没有在DecoratingHolder上明确地约束TU

More specifically, I think it's this part of the line: 更具体地说,我认为这就是这一部分:

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

That's causing the issue. 这导致了这个问题。 You're defining a ICopyable<T,TU> type, but TU has not been constrained to be ICopyable<T, TU> . 您正在定义ICopyable<T,TU>类型,但TU尚未被限制为ICopyable<T, TU> (one might be able to infer that from the rest of the class declaration/inheritance, but the compiler doesn't) Once you add the constraint, then the compiler knows that Value is a compatible ICopyable<T,TU> type. (可能能够从类声明/继承的其余部分推断出 ,但编译器没有)一旦添加约束,编译器就知道 Value是兼容的ICopyable<T,TU>类型。

This compiles fine for me (had to fix some other minor things with the pseudocode you provided): 这对我编译很好(必须使用你提供的伪代码修复其他一些小的东西):

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

EDIT: In retrospect, do you even need that constraint on ICopyable ? 编辑:回想起来,你甚至需要在ICopyable上有这个约束吗? Seems to not do much as you already generically define the outgoing type anyway. 似乎没有做太多,因为你已经一般地定义了传出类型。 Unless you have code elsewhere that depends on the fact that it returns ICopyable<T, TU> for some reason (it would inherently anyway as it would return a strongly typed TU or BooleanHolder or DecoratingHolder ) then consider dumping it. 除非你在其他地方有代码,这取决于它由于某种原因返回ICopyable<T, TU>这一事实(无论如何它会返回强类型的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 };
    }
}

EDIT: From your comment requiring a deep copy, keep the constraints then (you'll need them), and invoke Copy on Value (sorry, I must have missed that detail) 编辑:从你的评论需要深层复制,然后保持约束(你需要它们),并调用Copy Value (对不起,我一定错过了这个细节)

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() };
    }
}

The Copy methods for any given class should then make sure they perform a deep copy. 然后,任何给定类的Copy方法应确保它们执行深层复制。 (I would suggest renaming Copy to DeepCopy if your framework needs them to be deep copy and you don't want implementations to do shallows accidentally) (如果您的框架需要深层复制并且您不希望实现意外地执行浅滩,我建议将Copy重命名为DeepCopy

A cast worked for me: 演员为我工作:

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

I guess in this context the compiler doesn't go as far as to establish that TU and ICopyable<T, TU> is the same thing. 我想在这种情况下,编译器没有尽可能地确定TUICopyable<T, TU>是一回事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM