以下是我在测试中看到的一个问题,提出了一些问题:
给出以下代码:
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);
}
public delegate C func(B b);
public delegate T func<T,U>(U u);
并将A中的x
更改为public func<B,B> x;
时会发生什么?官方答案是:
至#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相同,因为两个定义都是等价的。
这是我不明白的地方:
x
中的x+=f;
的方法?具有“最接近”参数类型的重载方法是否为动态类型“this”所选择的那个?in
和out
声明,否则非变体通用委托不是? #3的答案有何意义?答案 0 :(得分:2)
带有“最近”参数类型的重载方法是否为动态类型“this”所选择的那个?
没有。如果这是真的,那么所有构造函数都会选择相同的方法(B C.f(B)
),因为它完全匹配并且是最派生类型。而是使用{em>静态类型的this
。
这意味着:
A
中,选择了C A.f(A)
,因为它是A
上匹配func
的唯一方法。B
中,B B.f(B)
被选中,因为它是B
上完全匹配的唯一方法。C
中,选择了B C.f(B)
,因为它完全匹配,并且以比B B.f(B)
更多的派生类型声明。除非使用
声明,否则非变体通用委托不是in
和out
?
是的,此类代理是不变的,这意味着您无法将func<B, B>
转换为func<A, B>
,func<B, C>
或func<A, C>
。但它不会改变从方法组转换为委托的规则,这些规则允许类似的转换,无论委托类型是否是通用的。