2013-11-23 48 views
0

下面是一個問題,我已經看到了一個測試,提出了一些問題:哪些重載的方法被添加到委託?

考慮下面的代碼:

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. 什麼,當我們改變委託定義到public delegate T func<T,U>(U u);包括和改變xpublic func<B,B> x;發生什麼呢?

官方答案是:

#1:

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

到#2:

它不能編譯,因爲被添加到x在B類的方法和C是根據參數的靜態類型選擇的。所以在B類B B.f(B)需要添加,但返回類型不匹配,並在類C B C.f(B)需要添加,但返回類型不匹配。

#3:

它打印相同的答案#1,因爲兩個定義是等價的。

這是我不明白:

  1. 如何被添加到x在該行x+=f;方法選擇出的所有重載的選擇嗎? 「最接近」參數類型的重載方法與選擇的「this」的動態類型是否相同?
  2. 除非與inout一起聲明,否則不是非泛型代表?如何回答#3是有意義的?

回答

2

是否選擇了「this」動態類型的「最近」參數類型的重載方法?

號。如果這是真的,那麼所有構造函數都會選擇同樣的方法(B C.f(B)),因爲它完全匹配,是最派生類型。相反,使用靜態類型的this

這意味着:

  1. AC A.f(A)被選擇的,因爲它是在A匹配func的唯一方法。
  2. B,B B.f(B)被選中,因爲它是唯一與B完美匹配的方法。
  3. C,B C.f(B)被選中,因爲它匹配完美並且聲明的派生類型比B B.f(B)更多。

是不是泛型委託非變異除非inout申報?

是的,這樣的代表是不變的,這意味着你不能轉換到func<B, B>func<A, B>func<B, C>func<A, C>。但是它不會改變從方法組到代表的轉換規則,這允許類似的轉換,無論委託類型是否是通用的。

+0

那麼哪些方法被添加到委託? 如果我添加到A類公共虛擬C f(B b){Console.WriteLine(「C A.f(B)」);返回新的C(2); }'那麼它將被添加,而不是'C A.f(A)'。請注意,它有2個現在屬於委託類型的方法,並且新方法與靜態類型不匹配。這是爲什麼? – Shookie

+0

@Shookie因爲它比'C f(A a)'更好。從'C f(A a)'到'B func(B b)',你必須做兩個改變。從'C f(B b)',只有一個變化。 – svick

+0

可能值得注意的是,即使是使用'in'和'out'裝飾聲明的代表,在涉及'Delegate.Combine'的情況下也不能支持協變或逆變。 – supercat