我只想确认一下我对C#中的Generics的理解。这已经出现在我使用的几个代码库中,其中使用通用基类来创建类型安全的派生实例。我正在谈论的一个非常简单的例子,
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();
}
}
似乎一旦将Generic引入继承层次结构或接口,就不能再以多态方式使用该类族,除非它本身就是内部的。这是真的吗?
答案 0 :(得分:12)
据我所知,使用代码不需要泛型类的细节(即,它不取决于T
是什么)。那么,为什么不介绍SomeClass<T>
将实现的接口,并使用此接口的实例。
E.g:
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
上以不同的方式运行,但消费代码不会改变。
答案 1 :(得分:9)
我认为你误解了仿制药的观点。泛型允许您概括需要类型的类,但不特别关心它是什么类型。例如,List<string>
是一个字符串列表,但List
是什么?如果没有任何列表,这是一个相当无用的概念。
每个专门的类(即List<string>
)都是它自己的不同类型,编译器将其视为此类。 可能来获取泛型类型本身(例如typeof(List<>)
),但在大多数情况下它是无用的,你肯定无法创建它的实例。
答案 2 :(得分: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(); }
}
答案 3 :(得分:1)
似乎一旦将Generic引入继承层次结构或接口,就不能再以多态方式使用该类族
正确,这与这种情况非常相似:
class StringContainer
{
}
class IntContainer
{
}
StringContainer container = new IntContainer(); // fails to compile
但你可以这样做:
class Container
{
}
class Container<T> : Container
{
}
Container container = new Container<String>(); // OK
答案 4 :(得分: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参数都是类型参数对于泛型类,而不是泛型类本身)。也可以有一个工厂,用于返回一种特定形式的泛型类型的实例。
答案 5 :(得分: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 } ;
}
}