C#generics和多态:一个矛盾?

我只是想确认一下我对C#中的Generics的理解。 这已经出现在我使用的几个代码库中,其中使用通用基类来创建类型安全的派生实例。 我正在谈论的一个非常简单的例子,

public class SomeClass { public virtual void SomeMethod(){ } } public class DeriveFrom :SomeClass { 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(); } } 

看来,一旦将Generic引入inheritance层次结构或接口,就不能再以多态方式使用该类族,除非它本身就是内部的。 真的吗?

据我所知,使用代码不需要generics类的细节(即,它不取决于T是什么)。 那么,为什么不介绍SomeClass将实现的接口,并使用该接口的实例。

例如:

 public interface ISome { void SomeMethod(); } public class SomeClass: ISome { public virtual void SomeMethod(){ } } public void DoSomethingClienty() { Factory factory = new Factory(); ISome someInstance = factory.Create(); someInstance.SomeMethod(); } 

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

我认为你误解了仿制药的观点。 generics允许您概括一个需要类型的类,但并不特别关心它是什么类型。 例如, List是一个字符串列表,但List是什么? 有一个没有任何列表是一个相当无用的概念。

每个专用类(即List )都是它自己的不同类型 ,编译器将其视为这样。 有可能获得generics类型本身(例如typeof(List<>) ),但在大多数情况下它是无用的,你肯定无法创建它的实例。

我更喜欢使用抽象类作为所有generics类型的基础。

 public abstract class SomeClass { public abstract void SomeMethod(); } public class SomeClass : SomeClass { public override void SomeMethod() { } } public class DeriveFrom : SomeClass { public override void SomeMethod() { base.SomeMethod(); } } 

看来,一旦将Generic引入inheritance层次结构或接口,就不能再以多态方式使用该类族

正确,它与这种情况非常相似:

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

但你可以这样做:

 class Container { } class Container : Container { } Container container = new Container(); // OK 

我想你要找的是:

  SomeClass(s​​omeType)someInstance = factory(someType).Create();
或者可能
   SomeClass(s​​omeType)someInstance = factory.Create(someType)();
要么
   SomeClass(s​​omeType)someInstance = factory.Create();

可以使用一组工厂类来创建不同的generics类,或者让工厂使用generics类型参数来指示它应该创建哪种generics类型(请注意,在任何一种情况下,type参数都是generics的类型参数类,而不是generics类本身)。 也可以有一个工厂,用于返回一种特定forms的generics类型的实例。

 public Class ReflectionReport { // 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 thangReport = new ReflectionReport(); ReflectionReport thongReport = new ReflectionReport(); ... 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 } ; } }