1

我有以下代码。为什么它总是采用“take(ICollection a)”方法?我认为它自己的对象应该是 LinkedList 或 HashSet,所以它应该调用另外两个 take 方法。

class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();

        ICollection<String>[] ary = { new LinkedList<String>(), new HashSet<String>() };

        foreach (ICollection<String> a in ary)
        {
            p.take(a);
        }

        for (int i = 0; i < ary.Length; i++)
        {
            p.take(ary[i]);
        }
    }


    public void take(HashSet<String> a)
    { }

    public void take(LinkedList<String> a)
    {}

    public void take(ICollection<string> a)
    { }
}
4

2 回答 2

7

方法分派是基于变量类型完成的,而不是运行时类型。这在 C# 语言规范 7.5.3 (Overload Resolution) 中有详细介绍 - 在整个部分中没有任何地方建议使用变量的运行时类型。调度由编译器根据“参数表达式”处理:

给定一个带有一组参数表达式 { E1, E2, ..., EN } 的参数列表 A 和两个适用的函数成员 MP 和 MQ,参数类型为 { P1, P2, ..., PN } 和 { Q1, Q2, ..., QN }, MP 被定义为比 MQ 更好的函数成员,如果

• 对于每个参数,从 EX 到 QX 的隐式转换并不比从 EX 到 PX 的隐式转换好,并且

• 对于至少一个论点,从EX 到PX 的转换优于从EX 到QX 的转换。

如果您希望它动态调度,您可以通过以下方式进行dynamic

 foreach (ICollection<String> a in ary)
 {
     dynamic o = a;
     p.take(o);
 }

或者,更短的形式:

 foreach (dynamic a in ary)
 {
     p.take(a);
 }
于 2013-09-05T16:18:20.863 回答
2

请参阅:http: //msdn.microsoft.com/en-us/library/aa691336 (v=vs.71).aspx

http://msdn.microsoft.com/en-us/library/aa691338(v=vs.71).aspx

来自 MSDN:

给定一个具有一组参数类型 {A1, A2, ..., AN} 的参数列表 A 和两个具有参数类型 {P1, P2, ..., PN} 和 {Q1, Q2 的适用函数成员 MP 和 MQ, ..., QN}, MP 被定义为比 MQ 更好的函数成员,如果:

  • 对于每个参数,从 AX 到 PX 的隐式转换并不比从 AX 到 QX 的隐式转换差,并且
  • 对于至少一个论点,从 AX 到 PX 的转换优于从 AX 到 QX 的转换。

在执行此评估时,如果 MP 或 MQ 以其扩展形式适用,则 PX 或 QX 指的是参数列表的扩展形式中的参数。

于 2013-09-05T16:17:23.353 回答