2012-07-09 114 views
1

..以及薯條的一側。C#使用泛型方法的MonoTouch方法重載和使用默認參數的非泛型方法

我有一個代碼庫,我正在爲Windows和MonoTouch編譯。在早晨的凌晨我編碼類似,其彙編了MonoTouch的,但無法在Windows上人爲的例子:

void Run() 
{ 
    // okay on both 
    exec("hello", 1); 

    // okay on MonoTouch 
    // compiler error on windows 
    exec("hello"); 
} 

interface IFace { void foo(); } 

void exec(string s, int n=0) 
{ 
    Console.Write("A"); 
} 
void exec<T>(T t) where T:IFace 
{ 
    Console.Write("B"); 
} 

在MonoTouch的,這個編譯和運行,打印:

AA 

在Windows上,這個例子給出了一個編譯時錯誤:

The type 'string' cannot be used as type parameter 'T' in the generic type or method 'App.Program.exec<T>(T)'. There is no implicit reference conversion from 'string' to 'App.Program.IFace'.

7.4.2 Overload Resolution C#的規範說的7.4.2.1 Applicable function member必須的參數相同數量:

The number of arguments in A is identical to the number of parameters in the function member declaration. 7.4.2.1

所以它似乎MonoTouch的編譯器正在考慮缺省參數適用函數成員搜索時,但Windows編譯器是沒有的。所以,候選函數成員是:

// exec with no default parameters. not applicable because no int supplied 
void exec(string,int); 

// exec with default value for the second parameter. 
// only considered on MonoTouch. 
void exec(string,int=0); 

// generic exec with string as the type, which is invalid 
// due to the IFace constraint. Invalid on both platforms. 
void exec<string>(string) : where T:IFace; 

所以,這是在MonoTouch的適用功能搜尋的錯誤,還是應該在Windows編譯器認爲是有效的默認參數的非泛型方法?

乾杯, 釐米

EDIT dlev的回答後,我檢測了兩個約束和不受約束通用方法,並且它出現在單聲道編譯器選擇正確的方法中的無約束的情況下。在受約束的情況下,Mono編譯器似乎在約束失敗時正在考慮約束或回溯來尋找替代方案。

問題/錯誤減少到:

void Run() 
{ 
    foo(1); 
    bar(1); 
} 

void foo(int a, int b = 0) { print("A"); } 
void foo<T>(T t) { print("B"); } 

void bar(int a, int b=0) { print("X"); } 
void bar<T>(T t) where T : IFace { print("Y"); } 

在Windows和MonoTouch的,foo正確打印B。但bar無法在Windows上編譯,但在MonoTouch上打印X

EDIT2 對於那些有興趣的人,我的解決方案是刪除默認參數,並要求顯式調用。在我的實際系統中,類型約束指定了兩個接口,所以我不能輕易將通用調用更改爲exec(IFace t) { ... }。我想我可以重構,但是這是我的系統的肉類和下面的解決我目前的編譯問題:

void exec(string a) { exec(a,0); } 
void exec(string a, int b) { ... } 
void exec<T>(T t) where T : IFace, IFace2 { ... } 

雙乾杯,釐米

+0

[錯誤報告6056(https://bugzilla.xamarin.com/show_bug.cgi?id=6056)提交xamarin: – cod3monk3y 2012-07-10 02:12:42

回答

1

這條線,從第7.5.3節。2規範表明,這是單色編譯器錯誤:

Otherwise if all parameters of MP have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in MQ then MP is better than MQ.

換句話說,如果你要替換一個值的可選參數,使適用的方法調用的法律,那麼該方法被認爲是一個更糟的匹配,然後不需要這樣的替換。

此外,the MS C# compiler does not back-track。一旦根據超負荷解決規則確定方法是最好的,則在該假設下繼續進行編譯。如果後面的分析確定選定的方法導致錯誤(比如說因爲替換的泛型參數違反了約束),那麼會通知您有關該錯誤。

而且yes, constraints are not part of the signature,所以重載決議不考慮T約束。

+0

感謝dlev​​!這是我在規範中遺漏的部分。我現在看到的問題是如何減少甚至進一步可選參數重載決議,由喬恩斯基特[這裏](http://stackoverflow.com/questions/2674417/c-sharp-4-conflicting-overloaded-methods-詳細介紹帶有可選參數) – cod3monk3y 2012-07-09 23:45:34

+0

@ cod3monk3y對。我只是指出,你得到的錯誤,因爲由於道路一般限制在C#中的工作,超負荷決議將不考慮其影響來進行。樂意效勞! – dlev 2012-07-09 23:48:08

+0

非常感謝!現在與Mono團隊溝通!查看我編輯的縮減測試用例。 – cod3monk3y 2012-07-10 00:07:04