..还有一份薯条。
我有一个正在为 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 函数成员必须具有相同数量的参数:
A 中的参数数量与函数成员声明中的参数数量相同。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 上的 Applicable Function Member 搜索中的错误,还是 Windows 编译器应该将默认参数化的非泛型方法视为有效?
干杯,厘米
编辑
在dlev
回答之后,我测试了受约束和不受约束的泛型方法,看来 Mono 编译器在不受约束的情况下选择了正确的方法。在受约束的情况下,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 上编译但X
在 MonoTouch 上打印。
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 { ... }
双倍干杯,厘米