Tri*_*nko 5 c# generics type-inference generic-type-argument
鉴于以下课程:
public static class EnumHelper
{
//Overload 1
public static List<string> GetStrings<TEnum>(TEnum value)
{
return EnumHelper<TEnum>.GetStrings(value);
}
//Overload 2
public static List<string> GetStrings<TEnum>(IEnumerable<TEnum> value)
{
return EnumHelper<TEnum>.GetStrings(value);
}
}
Run Code Online (Sandbox Code Playgroud)
选择两种通用方法之一应用哪些规则?例如,在以下代码中:
List<MyEnum> list;
EnumHelper.GetStrings(list);
Run Code Online (Sandbox Code Playgroud)
它最终调用EnumHelper.GetStrings<List<MyEnum>>(List<MyEnum>)(即Overload 1),即使它看起来同样有效EnumHelper.GetStrings<MyEnum>(IEnumerable<MyEnum>)(即Overload 2).
例如,如果我完全删除了重载1,那么调用仍然编译正常,而是选择标记为重载2的方法.这似乎使通用类型推断有点危险,因为它调用的方法直观地看起来像是更糟糕的匹配.我将List/Enumerable作为类型传递,这似乎非常具体,看起来它应该与具有类似参数的方法匹配(IEnumerable<TEnum>),但是它选择具有更通用的泛型参数的方法(TEnum value).
选择两种通用方法之一应用哪些规则?
规范中的规则 - 遗憾的是非常复杂.在ECMA C#5标准中,相关位从第12.6.4.3节开始("更好的功能成员").
但是,在这种情况下,它相对简单.这两种方法都适用,每种方法都会单独进行类型推断:
TEnum推断为List<MyEnum>TEnum推断为MyEnum接下来,编译器开始检查从参数到参数的转换,以查看一个转换是否比另一个转换"更好".这将进入第12.6.4.4节("从表达式转换得更好").
此时我们正在考虑这些转换:
List<MyEnum>到List<MyEnum>(TEnum推断为List<MyEnum>)List<MyEnum>到IEnumerable<MyEnum>(TEnum推断为MyEnum)幸运的是,第一条规则可以帮助我们:
给定从表达式E转换为类型T1的隐式转换C1,以及从表达式E转换为类型T2的隐式转换C2,如果以下至少一个成立,则C1是比C2更好的转换:
- E具有类型S,并且存在从S到T1而不是从S到T2的标识转换
还有就是从身份转换List<MyEnum>到List<MyEnum>,但不是一个身份转换List<MyEnum>到IEnumerable<MyEnum>,因此第一次转换是更好的.
没有任何其他转换需要考虑,因此重载1被视为更好的功能成员.
关于"更一般"与"更具体"参数的争论如果早期阶段在抢七中结束则有效,但事实并非如此:参数参数的"更好转换"在"更具体的参数"之前被考虑.
通常,重载分辨率都非常复杂.它必须考虑继承,泛型,无类型参数(例如,null文字,默认文字,匿名函数),参数数组,所有可能的转换.几乎每当有新功能添加到C#时,它都会影响重载分辨率:(
| 归档时间: |
|
| 查看次数: |
99 次 |
| 最近记录: |