2011-11-02 67 views
4

我有一个类层次结构,看起来像这样:类型推论的方法,以仿制药和类继承

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

'TConcrete'和'TElement'类型与返回或参数类型无关? –

+0

TConcrete是返回类型,我编辑了我的问题 – kshahar

+0

它看起来像你想要[更高级的类型](http://en.wikipedia.org/wiki/Kind_(type_theory)) c#,语言不支持 –

回答

4

这是不可能的,原因如下:

  1. 随着C#4,类型推断是“全有或全无” - 编译器不能推断出一些通用的参数而不是其他。
  2. 从C#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>(); 
+0

您的上一个建议(协变接口)解决了我的问题。谢谢! – kshahar

1

如果您让Base继承非泛型类或实现非泛型接口,则可以将方法限制为该类型。

否则,没有。如果可行,方法中的TConcrete.Element属性将没有类型。
如果你写

public TConcrete DoSomething<TConcrete>() where TConcrete : Base<> //Illegal! 
{ 
    TConcrete c = ...; 
    var b = c.Element; //What type is that variable? 
} 
0

如果DoSomething不知道(或护理)会发生什么,什么TElement是,你可能要考虑创建不带类型参数的父类:

class Base 
{ 
} 

class Base<TElement> : Base 
{ 
    public TElement Element { get; set; } 
} 

然后,您的DoSomething方法将在类Base上操作。

如果DoSomething需要知道类型参数,那么没有,没有办法做你想要的东西&你需要提供它。