为什么泛型类型的静态方法需要Type参数?

时间:2009-06-16 07:03:34

标签: c# generics

public class BinarySearchTree<T>
where T : IComparable<T>
{
    public static BinarySearchTree<char> InitializeSampleCharacterBST()
    {
        var bst = new BinarySearchTree<char>();

        bst.Insert('F');
        bst.Insert('B');
        bst.Insert('A');
        bst.Insert('D');
        bst.Insert('C');
        bst.Insert('G');
        bst.Insert('I');
        bst.Insert('H');

        return bst;
    }

class Program
{
        static void Main(string[] args)
        {
            var bst = BinarySearchTree.InitializeSampleCharacterBST();
        }
}

为什么这是非法的?它期望我为类的方法调用提供一个类型参数,这是没有意义的。泛型类或方法不能用于静态上下文中的类型参数。

它要我写这样的电话:

var bst = BinarySearchTree<foo>.InitializeSampleCharacterBST();

其中foo可以是我想要的任何类型,无论静态方法调用返回特定类型的通用对象这一事实。

4 个答案:

答案 0 :(得分:6)

班级BinarySearchTreeBinarySeachTree<Foo>完全分开;该语言允许泛型类型重载。也许在非通用的双胞胎类上声明这个方法:

public static class BinarySearchTree {
    public static BinarySearchTree<char> InitializeSampleCharacterBST() {...}
}
public class BinarySearchTree<T> {...} // rest of the code

否则...... T会使用什么?如果静态方法与静态字段对话怎么办?更不用说使用哪个T每个 T获得不同的静态字段(即SomeType<Foo>有单独的字段到SomeType<Bar>)。

答案 1 :(得分:6)

正如Marc所说,将类型重载为非泛型类有时很有用 - 在这种情况下就是这样。

至于为什么有必要,假设静态方法实际上实现为:

public static BinarySearchTree<char> InitializeSampleCharacterBST()
{
    Console.WriteLine(typeof(T));
    return null;
}

这将是完全有效的代码 - 它是泛型类型,因此它应该可以访问类型参数...但是你试图在不提供泛型类型参数的情况下调用该方法,因此它不可能工作。在您的情况下,您碰巧在方法中的任何地方都没有使用T,但这是巧合。这有点像有一个不使用this的实例方法:你没有使用实例,但你仍然无法将其称为静态方法。

除了具有单独的静态类之外,另一种可能有用的设计技术是将您的类型拆分为非泛型和通用部分。这样,如果你可以很难找出你所拥有的确切类型,你实际上并不需要知道它以便调用一些成员。例如,集合接口层次结构可能具有:

public interface ISomeCollection
{
    int Count { get; }
    void Clear();
}

public interface ISomeCollection<T> : ISomeCollection
{
    void Add(T item);
}

我自己将这种技术用于C#的Protocol Buffers端口,并且它被证明非常有用(如果有点复杂)。

答案 2 :(得分:3)

您忘记了类型参数不仅出现在方法的参数/返回类型中。它们也可以出现在实现中:

public static BinarySearchTree<char> InitializeSampleCharacterBST()
{
    var forSomeReason = new T();

通过将您的方法放在带有类型参数的静态类中,您说该方法的实现可能(现在或将来某个版本)依赖于该类型参数。

如果不是这种情况,你就把方法放错了地方。

答案 3 :(得分:0)

因为类型本身是Generic,所以你必须提供一个类型参数,即使你感兴趣的静态方法没有使用该类型参数。它只是C#中泛型的本质......它们在任何时候都不以非泛型形式存在。如果他们这样做,那将导致与相同类型的非泛型版本冲突。