2011-11-14 144 views
4

考慮以下控制檯應用程序:C#4.0默認參數

class Program 
{ 
    static void Main() 
    { 
     MyInterface test = new MyClass(); 
     test.MyMethod(); 

     Console.ReadKey(); 
    } 
} 

interface MyInterface 
{ 
    void MyMethod(string myString = "I am the default value on the interface"); 
} 

class MyClass : MyInterface 
{ 
    public void MyMethod(string myString = "I am the default value set on the implementing class") 
    { 
     Console.WriteLine(myString); 
    } 
} 

從該程序的輸出是:

I am the default value on the interface 

(1)爲什麼沒有指定參數作爲的方式在沒有提供值的情況下在接口上可選。我認爲默認值是實現細節。如果我們使用預選參數樣式編寫代碼,我們將在接口中創建兩個重載,並且默認值將在實現類中指定。即我們將有:

interface MyInterface 
{ 
    void MyMethod(); 

    void MyMethod(string myString); 
} 

class MyClass : MyInterface 
{ 
    public void MyMethod() 
    { 
     MyMethod("I am the default value set on the implementing class"); 
    } 

    public void MyMethod(string myString) 
    { 
     Console.WriteLine(myString); 
    } 
} 

,其輸出正如我們所期望的,

I am the default value set on the implementing class 

(2)我們爲什麼不能在實現類覆蓋默認值!

回答

4

.Net中的默認值實際上是基於編譯器的語法糖。編譯器在調用站點爲您添加默認值。它無法在編譯時知道對象的運行時類型,因此它必須插入接口中定義的值。

因此,它們不能在實現中被「重載」,因爲沒有什麼可以重載。

埃裏克利珀特寫了一個非常有趣的系列博客文章的主題的可選參數,其中第一個可以找到here

更新
從你的意見,你是在暗示要麼某種形式的「虛擬」參數(在運行時類型聲明),它的CLR必須「知道」的。我猜測這個實現被排除了,因爲與其給出的好處相比,成本(設計,記錄,實現,測試等)成本太高(儘管這只是一個猜測!)。 另外,還有默認的委託方法的選擇,即:

void M(bool y = false) { ... whatever ... } 

獲取重寫由編譯器爲:

void M() { M(false); } 
void M(bool y) { ... whatever ... } 

但走這路線導致過載,一旦多個可選參數的可能不可接受的水平並考慮命名的論點。

+0

Cheers Rich,我看到了問題。對於他們添加一個「可選」關鍵字而不是在界面上提供一個值是否更有意義?我不得不在界面上設置默認值。 – magritte

3

1)你的思維存在缺陷。你說默認值是一個實現細節。接口沒有實現細節。通過該邏輯,指定默認值實際上不屬於接口。

只需使用重載方法編寫接口。定義不僅更清晰,而且界面在與其他語言接口時將更加兼容,而且您不會遇到可選參數帶來的版本問題。

2)因爲接口定義了一個操作合同。接口說缺省值必須是某個東西......因此類必須以這種方式實現它。

+0

(1)的確,我同意,但是如果你不發表它,你會得到一個編譯器警告,因爲它不知道該參數是可選的。這導致我的問題(1)爲什麼你不能指定它爲可選的,而不提供值? – magritte

+0

@Tony Leeper - Eric Lippert也通過Twitter獲得了這個好系列的角落案例:http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases-part -one.aspx –