【问题标题】:Type inferences for a method, with generics and class inheritance具有泛型和类继承的方法的类型推断
【发布时间】:2011-11-02 14:02:57
【问题描述】:

我有一个如下所示的类层次结构:

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。

【问题讨论】:

  • TConcreteTElement 类型与返回或参数类型无关?
  • TConcrete 是返回类型,我已经编辑了我的问题
  • 看起来您正试图在 c# 中使用类似 higher-kinded types 的内容,但该语言不支持该语言

标签: c# generics inheritance c#-4.0 type-inference


【解决方案1】:

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

  1. 从 C# 4 开始,类型推断是“全有或全无” - 编译器无法推断某些通用参数,但不能推断其他参数。
  2. 从 C# 4 开始,无法指定通用“通配符”,例如 where TConcrete : Base&lt;???&gt;

这里有一些解决方法。

非泛型基类型:创建一个泛型的基类或接口类型。这是一种常见的模式;例如IEnumerable&lt;T&gt; : 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>();

【讨论】:

  • 您的最后一个建议(协变接口)解决了我的问题。谢谢!
【解决方案2】:

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

否则,不行。如果可能的话,您方法中的 TConcrete.Element 属性将没有类型。
如果你写会发生什么

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

【讨论】:

    【解决方案3】:

    如果DoSomething 不知道(或关心)TElement 是什么,您可能需要考虑创建不带类型参数的父类:

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

    然后,您的 DoSomething 方法将在类 Base 上运行。

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

    【讨论】:

      猜你喜欢
      • 2015-07-04
      • 1970-01-01
      • 2020-12-01
      • 2021-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多