鉴于以下课程:
File filepath = new File("C:/UIDriverProject/UIDriverPro/Test Folder/TESTDATA/TEST.dat");
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(filepath);
应用哪些规则来选择其两种通用方法之一?例如,在以下代码中:
$student = Student::where('roll_no','=',$roll)->first();
$book = Book::where('book_id','=',$bookno)->first();
它最终会调用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);
}
}
(即重载1),即使它似乎与调用List<MyEnum> list;
EnumHelper.GetStrings(list);
同样有效(即重载2)。
例如,如果我完全删除了重载1,那么调用仍然编译正常,而是选择标记为重载2的方法。这似乎使泛型类型推断有点危险,因为它调用的方法直观地看起来像更糟糕的比赛。我将List / Enumerable作为类型传递,这看起来非常具体,看起来应该与具有类似参数EnumHelper.GetStrings<List<MyEnum>>(List<MyEnum>)
的方法相匹配,但它选择的方法更通用,通用参数EnumHelper.GetStrings<MyEnum>(IEnumerable<MyEnum>)
。
答案 0 :(得分:7)
应用哪些规则来选择其两种通用方法之一?
规范中的规则 - 遗憾的是非常复杂。在ECMA C# 5 standard中,相关位从第12.6.4.3节开始(&#34;更好的函数成员&#34;)。
然而,在这种情况下,相对简单。这两种方法都是适用的,每种方法都会单独进行类型推断:
TEnum
被推断为List<MyEnum>
TEnum
被推断为MyEnum
接下来,编译器开始检查从参数到参数的转换,以查看一次转换是否更好&#34;比另一个。这将进入第12.6.4.4节(&#34;更好地转换自表达式&#34;)。
此时我们正在考虑这些转换:
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>
的身份转换,但并非来自{{1}的身份转换}到List<MyEnum>
,因此第一次转换更好。
没有其他任何转换需要考虑,因此重载1被视为更好的功能成员。
你的论点是关于&#34;更一般的&#34; vs&#34;更具体&#34;如果这个早期阶段在抢七局中结束,参数将是有效的,但它并没有:&#34;更好的转换&#34;参数的参数在&#34;更具体的参数&#34;。
之前考虑一般来说,重载分辨率都非常复杂。它必须考虑继承,泛型,无类型参数(例如null文字,默认文字,匿名函数),参数数组,所有可能的转换。几乎每当有新功能添加到C#时,它都会影响重载分辨率:(