2009-12-07 61 views
2

我刚开始学习泛型,并使用它们来重构我的代码中相当复杂的部分(我只使用c#一段时间,但我在其他语言方面颇有经验)。键入变量保存受约束泛型类的实例

我有我的类扩展基类的继承结构。在基类中,我实现了大部分功能。但我希望能够将这些儿童类与他们的兄弟姐妹的实例相关联。

下面是一些相关的代码的简化:

class ParentClass<T> 
    where T : ParentClass<T>, new() 
{ 

    public static T Create() 
    { 
     return new T(); 
    } 

    private object joinedItem; 

    public void Join<TJoinee>(TJoinee item) 
     where TJoinee : ParentClass<TJoinee>, new() 
    { 
     joinedItem = item; 
    } 

} 

class ChildOne : ParentClass<ChildOne> 
{ 
} 

class ChildTwo : ParentClass<ChildTwo> 
{ 
} 

有了这个代码在地方,我可以这样做:

var a = ChildOne.Create(); 
a.Join(new ChildTwo()); 

的问题是,我需要键入joinedItem为对象,当我真的想要键入它作为ParentClass<Something>。是否可以规定一个更具体的类型joinedItem?或者我只是可怕地滥用语言,应该采取一种完全不同的方法?

回答

3

您能否从ParentClass<T>中提取不依赖于T的接口?这样可以将joinedItem键入界面。

这似乎是,只要你可以采取它看起来像你试图做的事情(加入ParentClass<T>实例到ParentClass<U>实例)。

如果ParentClass<T>接口不依赖于T,那么在不知道T的情况下,将很难找到比对象更有用的接口。

+0

嗯 - 我可能可以去接口路由...我会看看实际的代码,看看是否有任何地方会掉下来... – vitch 2009-12-07 15:44:22

+0

但即使有*没有*在接口是独立于T的,你说的只是为了代码的意图和可读性的清晰性。即使它只是一个标记接口,编译器仍然会验证你不会做不可能的强制转换(即,你可以将一个'object'向下转换为'string',但是不能将'IJoinable'向下转换为'string' - 'string'不执行'IJoinable'。) – 2009-12-07 18:39:12

+0

好点Eamon – philsquared 2009-12-07 21:59:18

1

这里的核心问题是不可能表达变量必须是XYZ<_>类型的概念 - 具有任意类型参数。

可以表达的参数,那么你只需要添加约束(如你这样做),但你不能给变量(至少不无添加变量类型的类型参数列表,这很可能在语法上很丑陋)。

所以,如果你需要表达的XYZ<_>概念对任何类型_,你需要明确地表示这一概念作为一种类型(比如IXYZ),并确保所有XYZ<_> : IXYZ的实际上是从继承。通常,最灵活的方法是通过一个接口,但抽象基类也可以。

不幸的是,类型类一般不是泛型的一部分;-)。

+0

谢谢你的回答。当你说“没有将变量类型添加到类型参数列表”时,你的意思是在类级别添加类型参数吗? – vitch 2009-12-07 15:52:26

+0

在你的情况,是的,你需要在类级别添加类型参数,因为你想专门化一个类的变量 - 我不建议这样做,这可能会使你的代码更容易维护。然而,我所说的只是你使用的构造,Join方法有一个约束的泛型类型参数TJoinee。无论如何 - 如果有疑问,请使用接口来指定您需要的行为;这可能更容易和更灵活(因为一个类可以实现大量的接口)。 – 2009-12-07 18:34:46

+0

感谢您的澄清。我去接口路线,似乎都工作得很好! – vitch 2009-12-08 12:25:47