哪个重载方法被添加到委托?

时间:2013-11-23 18:39:00

标签: c# generics delegates covariance contravariance

以下是我在测试中看到的一个问题,提出了一些问题:

给出以下代码:

public delegate B func(B b);

public class A
{
    public func x;
    public int i = 2;
    public A(int i) { this.i = i; x += f; }
    public virtual C f(A a) { Console.WriteLine("C A.f(A)"); return new C(1); }
    public virtual A f(C c) { Console.WriteLine("A A.f(C)"); return new A(2); }
}

public class B: A{
    public B(int i) : base(i) { x += f; }
    public virtual B f(B b) { Console.WriteLine("B B.f(B)"); return new B(3); }
    public new C f(A a) { Console.WriteLine("C B.f(A)"); return new C(4); } 
}

public class C: B{
    public C(int i) : base(i) { x += f; }
    public new B f(B b) { Console.WriteLine("B C.f(B)"); return new C(5); }
    public override A f(C c) { Console.WriteLine("A C.f(C)"); return new A(6); }
}

以下主要内容:

static void Main(string[] args)
{
    C c = new C(12);
    A a = c.x(c);
    Console.WriteLine(a.i);
}
  1. 输出是什么?
  2. 如果我们将委托定义更改为:public delegate C func(B b);
  3. ,会发生什么
  4. 当我们将代理定义更改为public delegate T func<T,U>(U u);并将A中的x更改为public func<B,B> x;时会发生什么?
  5. 官方答案是:

    至#1:

    C A.f(A)
    B B.f(B)
    B C.f(B)
    5
    

    至#2:

    它不会编译,因为在B类和C类中添加到x的方法是根据参数的静态类型选择的。所以在类B中需要添加B B.f(B)但返回类型不匹配,并且在类C B C.f(B)中需要添加但返回类型不匹配。

    至#3:

    它打印的答案与#1相同,因为两个定义都是等价的。

    这是我不明白的地方:

    1. 如何从所有重载选项中选择添加到行x中的x+=f;的方法?具有“最接近”参数类型的重载方法是否为动态类型“this”所选择的那个?
    2. 除非使用inout声明,否则非变体通用委托不是? #3的答案有何意义?

1 个答案:

答案 0 :(得分:2)

  

带有“最近”参数类型的重载方法是否为动态类型“this”所选择的那个?

没有。如果这是真的,那么所有构造函数都会选择相同的方法(B C.f(B)),因为它完全匹配并且是最派生类型。而是使用{em>静态类型的this

这意味着:

  1. A中,选择了C A.f(A),因为它是A上匹配func的唯一方法。
  2. B中,B B.f(B)被选中,因为它是B上完全匹配的唯一方法。
  3. C中,选择了B C.f(B),因为它完全匹配,并且以比B B.f(B)更多的派生类型声明。
  4.   

    除非使用inout

    声明,否则非变体通用委托不是

    是的,此类代理是不变的,这意味着您无法将func<B, B>转换为func<A, B>func<B, C>func<A, C>。但它不会改变从方法组转换为委托的规则,这些规则允许类似的转换,无论委托类型是否是通用的。