2013-10-21 64 views
2

我支持一些具有可選參數和接口的代碼。可選參數和接口 - 意外結果

作爲簡化實例:我在實現類2中的界面中的默認值,並且1。

public interface IOptionalInterface 
{ 
    int Get(int x = 2); 
} 

public class ClassX : IOptionalInterface 
{ 
    public int Get(int x = 1) 
    { 
     return x; 
    } 
} 

此代碼按照我的預期通過。但是,當我將類作爲接口傳回並稍後調用它時,我從接口獲取可選參數;然後,這讓我感到驚訝。

private IOptionalInterface Build() 
    { 
     return new ClassX(); 
    } 

    public void Expect1() 
    { 
     var y = Build(); 
     Assert.AreEqual(y.Get(), 1); // fails, it returns 2. 
    } 

我錯過了哪些主要設計考慮因素使得這種優惠?

有一個乾淨的方式,以確保實現類到達設定的默認值?

+0

Eric Lippert在他的博客中對此進行了處理:http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases-part-one-as.aspx –

+1

這是預期的行爲。 –

+0

http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases-part-one.aspx – SLaks

回答

3

可選參數是爲調用調用一個純粹的編譯時的功能。

當你調用一個可選的參數的方法,編譯器查找該參數的默認值,並在調用會插入文本值。
因此,默認值根據調用網站的編譯時類型來解析。

1

這是因爲 - 就像擴展方法 - 可選參數是一個編譯器把戲不是真正的語言功能。

所以適當地 - 解決擴展方法的問題:

public interface IDoSomething { 
    void DoThis(int parameter); 
} 

public static class DoSomethingDefaults { 
    public static void DoThis(this IDoSomething x) { 
     x.DoSomething(123); //default value 
    } 
} 

/// 
new ClassThatImplementsDoSomething().DoThis(); 
new ClassThatImplementsDoSomething().DoThis(456); 

它並不像超光滑看上去真可選參數,但對於大多數的目的,他們做同樣的事情,並正常工作。

保持默認設置以及您的界面(我建議即使是相同的文件),並希望這會不會太辛苦了初來乍到你的項目,通過正在發生的事情追查。