【问题标题】:Constraint return type of static method to current class type将静态方法的返回类型约束为当前类类型
【发布时间】:2014-06-13 22:16:13
【问题描述】:

我在基类中有一个类层次结构和一个静态方法,所以子类也有这个静态方法。我很想定义一个静态方法,比如

public static IEnumerable<T> GetList<T>()
    where T : BaseClass, new()
{
    return new List<T>() { ... };
}

这样我就可以打电话了

var list = ChildClass.GetList();

列表为IEnumerable&lt;ChildClass&gt;。但是:我不知道如何告诉编译器将泛型类型推断为我调用的类的类型,所以这种用法会产生错误,我必须将其纠正为某种冗余

var list = ChildClass.GetList<ChildClass>();

我可以使用扩展方法(它们有 this 参数,允许编译器赶上),但我想在不实例化 ChildClass 的情况下这样做。

有没有办法不重复地做到这一点?

【问题讨论】:

    标签: c#


    【解决方案1】:

    你不能让编译器推断你调用的类,因为从技术上讲,你总是从定义方法的类中调用。

    允许您使用派生类名称的编译器只是为了方便。

    【讨论】:

      【解决方案2】:

      如果您可以忍受丑陋的 hack,您可以将 BaseClass 本身设为泛型,并将子类的类型作为参数传递给泛型参数,例如:

      class BaseClass<T> where T : BaseClass<T>, new()
      {
          public static IEnumerable<T> GetList()
          {
              return new List<T>() { new T() }; // whatever
          }
      }
      
      class Child : BaseClass<Child>
      {
      
      }
      
      class Child2 : BaseClass<Child2>
      {
      
      }
      

      现在Child.GetList() 返回一个IEnumerable&lt;Child&gt;,Child2.GetList() 返回一个IEnumerable&lt;Child2&gt;。

      【讨论】:

      • 直到有人创建EvilChild: BaseClass&lt;Child1&gt;
      • @Servy 是的,这就是为什么丑陋的黑客被称为丑陋和黑客的原因。
      【解决方案3】:

      如果您想知道为什么编译器无法解析类型,请继续阅读:

      首先,静态方法绑定到类型而不是对象。所以这里不能有任何多态行为。因此,您有一个孩子的事实,基类层次结构在这里并不重要,因为方法绑定到两个完全不同的实体。

      真正的问题在于 C# 编译器的类型推断功能。您必须向编译器提供一些关于 T 类型的信息。否则无法推断。

      您不能在左侧提供此信息,因为 C# 类型推断是从右到左工作的。换句话说:

      var ints = new {};
      

      完全没问题。因为右边的类型是匿名方法,ints 被解析为一个。但是:

      int[] ints = new [] {};
      

      行不通。编译器抱怨“没有为隐式类型数组找到最佳类型”。换句话说,编译器不能使用左侧的信息来确定右侧的类型应该是什么。

      你的问题

      var list = ChildClass.GetList();
      

      不向编译器提供有关 T 是什么的任何信息!即使你有 type 而不是 var 也不会有所作为。

      【讨论】:

      • 很好,感谢您的回答!我知道从右到左的干扰,但我不确定它在那里适用多少。如果您考虑链调用list.Where(...).Select(...),那么类型信息实际上会向右流动——您不必在最后一个选择中输入 lambda,因为您知道list 是什么。同样,可以有一个 THIS 类型级别等效于 this 关键字,这将在静态方法中可用。当然,我知道这样做会过于复杂,因为静态方法是“继承的”这一事实本身就令人惊讶。 :-)
      猜你喜欢
      • 1970-01-01
      • 2015-03-26
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多