简体   繁体   English

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

[英]Why does a static method on a generic type require a Type parameter?

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();
        }
}

Why is this illegal? 为什么这是非法的? It's expecting me to provide a type parameter to the method call for the class which makes no sense. 期望我为没有意义的类的方法调用提供类型参数。 A generic class or method has no use for a type parameter in a static context. 泛型类或方法在静态上下文中没有使用类型参数。

It wants me to write the call like this: 它想让我这样写电话:

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

Where foo can be any type I want regardless of the fact that the static method call returns a specifically typed generic object. foo可以是我想要的任何类型,而不管静态方法调用返回特定类型的泛型对象的事实。

the class BinarySearchTree and BinarySeachTree<Foo> are completely separate; BinarySearchTreeBinarySeachTree<Foo>完全分开; the language allows generic type overloading. 该语言允许泛型类型重载。 Perhaps declare this method on a non-generic twin class: 也许在非泛型孪生类上声明此方法:

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

Otherwise... what T would it use? 否则...它将使用什么T And what if the static method talked to static fields? 而且,如果静态方法与静态字段对话怎么办? Let alone which T to use, each T gets different static fields (ie SomeType<Foo> has separate fields to SomeType<Bar> ). 更不用说要使用哪个T了, 每个 T都会获得不同的静态字段(即SomeType<Foo>SomeType<Bar>具有不同的字段)。

As Marc said, it's sometimes useful to overload the type to have a non-generic class - and it would be in this case. 正如Marc所说的,有时将类型重载为具有非泛型类很有用-在这种情况下就是如此。

As for why it's necessary, suppose that the static method were actually implemented as: 至于为什么有必要,假设静态方法实际上实现为:

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

That would be perfectly valid code - it's in a generic type, so it should have access to the type parameter... but you're trying to call the method without providing a generic type parameter, so it couldn't possibly work. 那将是完全有效的代码-它是泛型类型,因此它应该可以访问类型参数...但是您尝试在不提供泛型类型参数的情况下调用该方法,因此它可能无法工作。 In your case you happen to not use T anywhere within the method, but that's a coincidence. 在您的情况下,您碰巧不在方法中的任何地方使用T ,但这是一个巧合。 It's a bit like having an instance method which doesn't use this : you're not using the instance, but you still can't call it as if it were a static method. 这有点像拥有一个不使用this方法的实例方法:您没有使用该实例,但是您仍然无法像调用静态方法一样调用它。

As well as having separate static classes, another design technique which can be useful is to split your type into non-generic and generic pieces. 除了具有单独的静态类之外,另一种有用的设计技术是将您的类型分成非通用和通用部分。 That way, in cases where it can be awkward to work out which exact type you have, you don't actually need to know it in order to call some of the members. 这样,在弄清楚您拥有哪种确切类型的情况下,您实际上不需要知道它即可调用某些成员。 For example, a collection interface hierarchy might have: 例如,收集接口层次结构可能具有:

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

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

I've used this technique myself for my Protocol Buffers port to C#, and it's proved very useful (if somewhat complicated). 我已经在C#的Protocol Buffers端口中使用了此技术,事实证明它非常有用(如果有些复杂的话)。

You're forgetting that type parameters don't only appear in the parameter/return type of a method. 您忘记了类型参数不仅会出现在方法的参数/返回类型中。 They can also appear in the implementation: 它们也可以出现在实现中:

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

By placing your method inside a static class with a type parameter, you are saying that the implementation of the method may (now or in some future revision) depend upon that type parameter. 通过将您的方法放在带有类型参数的静态类中,您的意思是该方法的实现可能(现在或将来会修订)取决于该类型参数。

If this isn't the case, you've put the method in the wrong place. 如果不是这种情况,则将方法放在错误的位置。

Because the type itself is Generic, you have to provide a type argument, even if the static method you are interested in does not make use of that type argument. 因为类型本身是泛型的,所以即使您感兴趣的静态方法不使用该类型参数,也必须提供一个类型参数。 Its just the nature of generics in C#...they don't exist in a non-generic form at any time. 它只是C#中泛型的性质...它们在任何时候都不以非泛型形式存在。 If they did, that would cause conflicts with a non-generic version of the same type. 如果这样做,将与同类型的非通用版本产生冲突。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM