2012-03-27 56 views
3

在給出的示例中(對於代碼樣式感到遺憾,它符合緊湊自包含的repro的興趣),所調用的方法始終是B中的虛方法有額外的整數參數,但我期望在C中實現的方法是一個被調用的方法。C#爲可選參數和多級繼承選擇一種不同的方法

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace MethodChoosing 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      C c = new C(); 
      c.M(); 

      Console.ReadKey(); 
     } 
    } 

    public class A 
    { 
     public virtual void M(bool? a = null) 
     { 
      Console.WriteLine("base base"); 
     } 
    } 

    public class B : A 
    { 
     public override void M(bool? a = null) 
     { 
      Console.WriteLine("base override"); 
     } 

     public virtual void M(bool? a = null, int? b = null) 
     { 
      Console.Write("base new"); 
     } 
    } 

    public class C : B 
    { 
     public override void M(bool? a = null) 
     { 
      Console.WriteLine("pick me!"); 
     } 
    } 
} 

,輸出 「新基礎」。這顯然不是我所期望的行爲,是否有人能夠解釋推理?

編輯: 改變主,使c.M有一個true或null參數仍然選擇不正確的方法。

+0

退房這個問題: http://stackoverflow.com/questions/8909811/c-sharp-optional-parameters-on-overridden-methods它可能不是同樣的事情,但它接近。 – 2012-03-27 13:45:20

+0

你已經結合了重載和可選參數。你永遠不應該那樣做。對於你的犯罪,我判你閱讀[Eric Lippert關於可選參數角落案件的四部分系列](http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases -part-one.aspx)加上這個[「如果它傷害,那麼不要這樣做」prequel](http://blogs.msdn.com/b/ericlippert/archive/2011/02/10/optional-arguments - 酮兩種-ends.aspx)。 – 2012-03-27 13:46:55

+0

我從來不會這樣做,這是一個隨機的想法,變成了一些調查:) – 2012-03-27 16:00:47

回答

4

該規範的第7.4節指出,在成員查找過程中正在考慮的可訪問方法集中排除了覆蓋方法。考慮到原始問題中的方法,類A有一個未覆蓋的方法,類B有一個未覆蓋的方法,而類C沒有。從該集合中的兩個方法中,編譯器在大多數派生類中選擇匹配方法(在這種情況下,類B是「基本新」函數)。

如果B類中的匹配函數不存在,那麼最好的函數匹配就是A類中的虛函數。在這種情況下,該對象的運行時類型將用於選擇哪一個在A,B或C類中的重寫函數將被選擇。作爲問題的陳述,因爲該方法被稱爲C類的對象,將是「接我!」功能。

1

對於c.M(),假定調用M(null, null)。 這是可選參數如何工作的方式。 如果您要撥打C.M,請致電C.M(null)或在C類中覆蓋M(bool? a = null, int? b = null)

+0

如果你打電話C.M(真)它仍然會從B類選擇虛擬。 – 2012-03-27 14:50:19

1

這就是所謂的不明確的調用。由於您有兩個方法僅由一個可選參數分隔,因此應用程序似乎選擇了可滿足大多數參數的方法。

編輯:@lazyberezovsky說,我在那裏並不完全正確。如果您有一種方法可以滿足NO參數,則優先

+0

啊,是的,我剛剛匹配C中的參數數量,然後打印出「接我!」。 – 2012-03-27 14:13:52

+0

將參數傳遞給C.M,既是true也是null,它仍然選擇相同的方法。這似乎很奇怪,因爲我明確提供了足夠的參數來完成採用一個參數的方法,但它仍然選擇具有最多可選參數的參數。 – 2012-03-27 14:52:16

+0

是的,因爲您仍然匹配具有最多參數的方法。可選參數的樂趣:D。 – mattytommo 2012-03-27 14:59:28