2009-11-29 89 views
16

我只想确认我对C#中泛型的理解。这已经出现在我工作过的几个代码库中,其中泛型基类用于创建类型安全派生实例。我正在谈论的一个非常简单的例子,C#泛型和多态:一个矛盾吗?

public class SomeClass<T> 
{ 
    public virtual void SomeMethod(){ } 
} 

public class DeriveFrom :SomeClass<string> 
{ 
    public override void SomeMethod() 
    { 
     base.SomeMethod(); 
    } 
} 

当我然后想要以多态方式使用派生实例时出现问题。

public class ClientCode 
{ 
    public void DoSomethingClienty() 
    { 
     Factory factory = new Factory(); 
     //Doesn't compile because SomeClass needs a type parameter! 
     SomeClass someInstance = factory.Create(); 

     someInstance.SomeMethod(); 
    } 
} 

看来,一旦你介绍一个通用成一个继承体系或接口,可以不再使用类家族中多态的方式也许除了内部本身。真的吗?

+3

在我看来,似乎SomeClass 是DeriveFrom的基类,而不是SomeClass,这是你似乎认为它应该是。 – Thanatos 2009-11-29 06:58:34

回答

11

就我所见,消费代码并不需要泛型类的具体细节(即,它不取决于什么是T)。那么,为什么不介绍SomeClass<T>将实现的接口,并使用此接口的实例。

例如为:

public interface ISome 
{ 
    void SomeMethod(); 
} 

public class SomeClass<T>: ISome 
{ 
    public virtual void SomeMethod(){ } 
} 

public void DoSomethingClienty() 
{ 
    Factory factory = new Factory(); 
    ISome someInstance = factory.Create(); 

    someInstance.SomeMethod(); 
} 

现在,SomeClass<T>子类可以不同在不同的T s运行,但消耗的代码不会改变。

+0

我认为这是最好的解决方案。我们只扩展客户端关心的接口,并将引擎盖下的泛型隐藏起来。 – 2009-11-29 14:14:52

9

我想你是误会仿制药的地步。泛型允许你概括一个需要类型的类,但并不特别关心它是什么类型。例如,List<string>是一个字符串列表,但你会一个List是什么?没有任何东西的清单是一个相当无用的概念。

每个专门的类(即List<string>)是它是它自己的不同类型,编译器将它视为这样。它可能是以获得泛型类型(例如typeof(List<>)),但在大多数情况下它是无用的,并且您当然不能创建它的实例。

2

我宁愿使用抽象类作为所有泛型类型的基础。

public abstract class SomeClass 
{ 
    public abstract void SomeMethod(); 
} 

public class SomeClass<T> : SomeClass 
{ 
    public override void SomeMethod() { }    
} 

public class DeriveFrom<String> : SomeClass<String> 
{ 
    public override void SomeMethod() { base.SomeMethod(); }    
} 
+0

确实,但是'Factory'会在这里工作吗? – 2009-11-29 08:58:09

+0

不知道Nick提到的“Factory”的实现。但我很确定,它可以很好地在抽象的非泛型“SomeClass”中实现。 – 2009-11-30 05:56:16

+0

@Amby但是,如果抽象void SomeMethod()的返回类型为T并且参数类型为T,你会怎么做?那么你不能隐藏非泛型抽象类下的泛型。我会很感激您的答案或提示:) – Elisabeth 2012-08-31 18:55:17

0

我想你要找的是什么:

 SomeClass(of someType) someInstance = factory(of someType).Create(); 
or maybe 
    SomeClass(of someType) someInstance = factory.Create(of someType)(); 
or 
    SomeClass(of someType) someInstance = factory.Create(); 

它可能有一组工厂类来创建不同的泛型类,或有一个泛型类型参数的工厂指出它应该创建哪个泛型类型(注意无论哪种情况,type参数都是泛型类的类型参数,而不是泛型类本身)。也可以有一个工厂,它被设计为返回一种特定形式的泛型类型的实例。

0

看来,一旦你介绍一个通用成一个继承体系或接口,可以不再使用类家族中多态的方式

正确的,这是相当类似这种情况:

class StringContainer 
{ 
} 

class IntContainer 
{ 
} 

StringContainer container = new IntContainer(); // fails to compile 

,但你可以这样做:

class Container 
{ 
} 

class Container<T> : Container 
{ 
} 

Container container = new Container<String>(); // OK 
0
public Class ReflectionReport<T> 
{ 
    // This class uses Reflection to produce column-based grids for reporting. 
    // However, you need a type in order to know what the columns are. 
} 

... so, in another class you have... 

public Class ReflectionReportProject { 
    ReflectionReport<Thang> thangReport = new ReflectionReport<Thang>(); 
    ReflectionReport<Thong> thongReport = new ReflectionReport<Thong>(); 



    ... some more stuff ... 

    // Now, you want to pass off all of the reports to be processed at one time.... 
    public ReflectionReport<????>[] ProvideReports() 
    { 
     return new ReflectionReport<????>[] { thangReport, thongReport } ; 
    } 
} 
+2

以上是一个如何与泛型多态性真正有用的例子。 – user1126454 2012-03-09 22:14:32