我有一个类层次结构,如下所示:
class Base<TElement>
{
public TElement Element { get; set; }
}
class Concrete : Base<string>
{
}
我想编写一个接受Base
子类的方法:
public TConcrete DoSomething<TConcrete, TElement>()
where TConcrete : Base<TElement>
{
}
有没有办法定义DoSomething,而无需定义TElement
?
理想的解决方案是,如果编译器可以自动计算TElement
,那么调用代码将如下所示:
var item = DoSomething<Concrete>();
我正在使用C#4.0。
答案 0 :(得分:4)
由于以下原因,这是不可能的:
where TConcrete : Base<???>
。以下是一些解决方法。
非通用基类型:创建不泛型的基类或接口类型。这是一种常见的模式;例如IEnumerable<T> : IEnumerable
。
协变接口:使用C#4通用接口协方差,您可以创建一个类型安全的解决方案,不需要使用“丑陋”的非通用成员来混乱您的类型:
public interface IBase<out TElement>
{
TElement Element { get; }
}
class Base<TElement> : IBase<TElement>
{
public TElement Element { get; set; }
}
class Concrete : Base<string> { }
然后:
// Won't work with value types.
public TConcrete DoSomething<TConcrete>()
where TConcrete : IBase<object> { }
并称之为:
var item = DoSomething<Concrete>();
答案 1 :(得分:1)
如果使Base
继承非泛型类或实现非泛型接口,则可以将方法限制为该类型。
否则,不。如果可能的话,方法中的TConcrete.Element
属性将没有类型
如果你写
public TConcrete DoSomething<TConcrete>() where TConcrete : Base<> //Illegal!
{
TConcrete c = ...;
var b = c.Element; //What type is that variable?
}
答案 2 :(得分:0)
如果DoSomething
不知道(或关心)TElement
是什么,您可能希望在没有type参数的情况下创建父类:
class Base
{
}
class Base<TElement> : Base
{
public TElement Element { get; set; }
}
然后,您的DoSomething
方法将在类Base上运行。
如果DoSomething
需要知道类型参数,那么不,没有办法做你想要的事情&amp;你需要提供它。