【问题标题】:Overloading, generic type inference and the 'params' keyword重载、泛型类型推断和“params”关键字
【发布时间】:2009-11-30 15:39:47
【问题描述】:

我刚刚注意到重载解析的一个奇怪行为。

假设我有以下方法:

public static void DoSomething<T>(IEnumerable<T> items)
{
    // Whatever

    // For debugging
    Console.WriteLine("DoSomething<T>(IEnumerable<T> items)");
}

现在,我知道这个方法通常会用少量显式参数调用,所以为了方便我添加这个重载:

public static void DoSomething<T>(params T[] items)
{
    // Whatever

    // For debugging
    Console.WriteLine("DoSomething<T>(params T[] items)");
}

现在我尝试调用这些方法:

var items = new List<string> { "foo", "bar" };
DoSomething(items);
DoSomething("foo", "bar");

但在这两种情况下,都会调用 params 的重载。我本来希望在 List&lt;T&gt; 的情况下调用 IEnumerable&lt;T&gt; 重载,因为它似乎更匹配(至少对我而言)。

这种行为正常吗?谁能解释一下?我在 MSDN 文档中找不到任何明确的信息...这里涉及的重载解决规则是什么?

【问题讨论】:

    标签: c# generics type-inference params-keyword overload-resolution


    【解决方案1】:

    C# 3.0 规范的第 7.4.3 节是这里的相关位。基本上参数数组被扩展了,所以你在比较:

    public static void DoSomething<T>(T item)
    

    public static void DoSomething<T>(IEnumerable<T> item)
    

    第一场比赛的T被推断为List&lt;string&gt;,第二场比赛的T被推断为string

    现在考虑参数到参数类型的转换——第一个是List&lt;string&gt;List&lt;string&gt;;第二个是List&lt;string&gt;IEnumerable&lt;string&gt;。按照 7.4.3.4 中的规则,第一次转换优于第二次。

    反直觉的位是类型推断。如果您将其排除在等式之外,它将按您的预期工作:

    var items = new List<string> { "foo", "bar" };
    DoSomething<string>(items);
    DoSomething<string>("foo", "bar");
    

    此时,每次调用中只有一个适用的函数成员。

    【讨论】:

    • 谢谢乔恩,这正是我需要的解释。是否有某种解决方法可以使其按我的意愿工作?如果不是,我想我将不得不使用不同的名称......
    • 是的,我注意到如果我明确指定泛型类型参数,它会起作用。但是我失去了类型推断的好处......
    • 我建议使用不同的名称,只是为了清楚起见 - 或者如果您只想将它​​用于多个项目,您可以使用 (T first, params T[] others)
    • 不错的乔恩。在这里要问的一个好问题是“如果没有 IE 重载,您希望发生什么?”在这种情况下,显然最好的行为是推断 T 是 List。类型推断的一个重要设计原则是,无论存在什么其他候选,它都会给出相同的结果。如果在添加新的重载时类型推断发生了变化,那就太奇怪了!
    • 这里还有另一种奇怪的情况可能会混淆,那就是DoSomething("foo") - 在这种情况下,它看起来就像一个明确的情况,只有参数数组重载才能工作...但当然IEnumerable&lt;T&gt; 重载也适用,T=char。总是很容易错过:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多