约束将静态方法的类型返回到当前类类型

时间:2014-06-13 13:58:15

标签: c#

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

这样的静态方法
public static IEnumerable<T> GetList<T>()
    where T : BaseClass, new()
{
    return new List<T>() { ... };
}

所以我可以打电话给

var list = ChildClass.GetList();

,列表为IEnumerable<ChildClass>。但是:我不知道如何告诉编译器推断泛型类型是我调用的类的类型,所以这种用法产生错误,我必须纠正它以某种方式冗余

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

我可以使用扩展方法(它们有this参数,允许编译器捕获),但我希望在没有实例化ChildClass的情况下执行此操作。

有没有办法在不重复的情况下完成此任务?

3 个答案:

答案 0 :(得分:2)

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

允许您使用派生类名称的编译器只是一种便利。

答案 1 :(得分:1)

如果你可以忍受丑陋的黑客攻击,你可以使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<Child>Child2.GetList()返回IEnumerable<Child2>

答案 2 :(得分:1)

如果您想知道编译器无法解析类型的原因,请继续阅读:

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

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

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

var ints = new {};

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

int[] ints = new [] {};

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

在你的问题中

var list = ChildClass.GetList();

不向编译器提供有关T是什么的任何信息!即使你有类型而不是var也没有什么区别。