在 C# 中继承泛型
Posted
技术标签:
【中文标题】在 C# 中继承泛型【英文标题】:Inheriting a generic in c# 【发布时间】:2015-05-12 15:00:44 【问题描述】:我继承了一个大型代码库,并且正在尝试在框架中实现一些新功能。基本上,为了以“正确”的方式进行操作,我必须修改框架的整个结构。因为我不是设计框架的人,也不是读心者,所以这样做可能不会发生(尽管我真的很想自己从头开始重新设计它)。
所以为了做我想做的事,我正在尝试实现一个装饰器模式。 This answer from maliger 表明我在下面所做的事情是完全有效的。但是,mono 似乎不喜欢它。当我声明 HappyDecorator
时,它抱怨 T
不能派生出来
请原谅这个过于简单的例子,但它明白了重点。
public class HappyObject
public virtual void print()
Console.WriteLine ("I'm happy");
public class VeryHappyObject : HappyObject
public override void print()
Console.WriteLine ("I'm very happy");
public void LeapForJoy()
Console.WriteLine("Leaping For Joy!");
public class SuperHappyObject : VeryHappyObject
public override void print()
Console.WriteLine ("I'm super happy!");
public void DieOfLaughter()
Console.WriteLine("Me Dead!");
public class HappyDecorator<T> : T where T : HappyObject
public string SpecialFactor get; set;
public void printMe()
Console.WriteLine (SpecialFactor);
print();
class MainClass
public static void Main (string[] args)
HappyDecorator<HappyObject> obj = new HappyDecorator<HappyObject> ();
obj.SpecialFactor = Console.ReadLine();
obj.printMe();
【问题讨论】:
您是否收到错误消息?或者它的行为与预期有何不同? 这不是遵循装饰器模式的方式。 obj obect 应该在他的构造函数中获得一个 HappyDecorator。 您不能继承泛型类型参数,这正是您的代码示例的错误消息所说的。哪一部分你不明白? 听起来你应该摆脱所有 cr_p 并改用System.Action<T>
。创建类只是为了保存这样的函数被称为“名词王国中的执行”,这是一种疾病,主要影响设计糟糕的古老语言,如 java,而 C# 具有适当的特性来处理这个问题,而无需不得不创建无穷无尽的类层次结构。
你不能继承T
。要么继承HappyObject
,要么注入并包装T
。我会选择后者。
【参考方案1】:
您正在向 T 键入 HappyDecorator,但在该类中没有可使用的 T 实例。
public class HappyDecorator<T> where T : HappyObject
private readonly T _instance;
public HappyDecorator(T instance)
_instance = instance;
public string SpecialFactor get; set;
public void printMe()
Console.WriteLine(SpecialFactor);
_instance.print();
另一种选择是使用泛型方法而不是泛型类来构造它。不过,它并不是真正的装饰器:
public class HappyDecorator
public string SpecialFactor get; set;
public void printMe<T>(T instance) where T : HappyObject
Console.WriteLine(SpecialFactor);
instance.print();
然后像这样调用:
HappyDecorator obj = new HappyDecorator();
obj.SpecialFactor = Console.ReadLine();
obj.printMe(new HappyObject());
【讨论】:
HappyDecorator
在 OPs 代码示例中继承 T
,所以它是实例本身。
除非语法不正确且无法编译。那么它是否应该继承HappyObject,在这种情况下,泛型的好处就没有了。
我知道这不是一个有效的语法。在您提出解决方法之前,我希望您的回答能说明这一点:)
第二个绝对不是我想做的,对象必须以某种方式继承HappyObject
,并且必须能够这样使用。第一个解决方案带来了一个问题,因为如果我将 VeryHappyObject
或 SuperHappyObject
传递给构造函数,我将无法访问这两个对象中包含的特殊字段。不幸的是,我的例子没有正确反映这一点。我将对其进行编辑以使其更清晰。
放弃HappyDecorator 类,将SpecialFactor 和printMe 移至基类,只创建您关心的正确实例怎么样?否则装饰器类将需要暴露 T 以便调用它的方法。【参考方案2】:
我认为这就是你想要做的:
public interface IhappyObject
void Print();
public class HappyObject : IhappyObject
private IhappyObject obj;
public HappyObject(IhappyObject obj)
this.obj = obj;
public void Print()
obj.Print();
public class VeryHappyObject : IhappyObject
public void Print()
Console.WriteLine("I'm very happy");
public class SuperHappyObject : IhappyObject
public void Print()
Console.WriteLine("I'm super happy!");
static void Main(string[] args)
HappyObject obj = new HappyObject(new SuperHappyObject());
obj.Print();
【讨论】:
嗯,不完全是。我没有选择传统装饰器模式的原因是我想避免显式包装方法。当然,实际的代码(我拒绝称这种可恶是我自己的工作)比我提供的示例要复杂得多。 例如,假设VeryHappyObject
和SuperHappyObject
的参数不包含在接口IHappyBbject
中。如果我正确理解了您的实现,具体来说,假设他们分别拥有LeapForJoy()
和DieOfLaughter()
方法(但不是两者都有)。然后我必须在界面中定义这两个函数,这并不是我想要做的,因为实际上这些对象比我想象的要复杂得多,这样做是真正的 PITA。以上是关于在 C# 中继承泛型的主要内容,如果未能解决你的问题,请参考以下文章