2012-07-09 110 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