给出两种比较方法的实现:
// compares by Key...
private static int CompareByKey(KeyValuePair<int, string> x, KeyValuePair<int, string> y)
{
return x.Key.CompareTo(y.Key);
}
// compares by Value...
private static int CompareByValue(KeyValuePair<int, string> x, KeyValuePair<int, string> y)
{
return x.Value.CompareTo(y.Value);
}
为什么下面的条件运算符代码块不会编译:
Comparison<KeyValuePair<int, string>> sortMethod;
sortMethod = isSortByActualValue ? CompareByKey : CompareByValue;
编译错误:“无法确定条件表达式的类型,因为'方法组'和'方法组'之间没有隐式转换”
但是,使用if-else的等效代码块没有任何问题:
Comparison<KeyValuePair<int, string>> sortMethod;
if (isSortByActualValue)
sortMethod = CompareByKey;
else
sortMethod = CompareByValue;
(上述两项任务都很好)
条件运算符也是如此,如果我转换了比较委托:
Comparison<KeyValuePair<int, string>> sortMethod;
sortMethod = isSortByActualValue ? (Comparison<KeyValuePair<int, string>>) CompareByKey : CompareByValue;
(在上面的任务中都很好,即使施法只是在真正的部分施放时)
答案 0 :(得分:7)
错误方法实际上说的都是,但它不是很直观。如果在不调用方法的情况下使用方法名称,则表示您正在处理方法组。 “group”,因为方法可以重载,名称可以指示任何重载方法。
现在,方法组可以隐式转换为具有匹配签名的委托,这就是if
中的作业可行的原因。
到目前为止,这么好。但是,条件运算符?:
需要推导出可以隐式转换其第二个和第三个参数的公共类型,并且它不会考虑所有转换(这会产生各种问题)。它只是查看两个参数是否具有相同的类型,或者是否可以隐式转换为另一个。
这不是这里的情况:虽然两个参数都是方法组,但它们实际上是具有不同类型的不同的方法组,并且您无法将一个方法组转换为另一个方法组。尽管两者都可以很容易地转换为委托,但编译器禁止这种用法。
顺便说一下,其他类型也是如此:
object = someBool ? "" : New List<Integer>();
由于同样的原因,也无法编译。同样,我们可以通过显式地将任一参数转换为公共基类型来进行编译:
object = someBool ? (object) "" : New List<Integer>();
答案 1 :(得分:3)
如果您的表达式与CompareByKey
类似,则它没有任何特定的.Net类型,但具有特殊类型“方法组”。那是因为你可能有几个名为CompareByKey
的方法,并且你不清楚你想要哪一个(即使你只有一个方法它也能完全相同)。此外,还不清楚你想要什么代表类型,例如Comparison<KeyValuePair<int, string>>
或Func<KeyValuePair<int, string>, int>
。
你可以用方法组做什么?您可以使用它们来显式创建委托(new Comparison<KeyValuePair<int, string>>(CompareByKey)
),它们也可以隐式转换为委托。这就是您的if
版本有效的原因。
那么,这与你的问题有什么关系?当你有一个条件运算符时,编译器必须弄清楚整个表达式的类型,它不能使用你赋给它的变量的类型(这不是类型推断在C#中的工作方式)。并且由于两个表达式都是方法组,并且方法组被视为不同类型,彼此之间没有隐式转换,因此无法确定整个表达式的类型。这就是你得到错误的原因。
您已找到修复:要么不使用条件运算符,要么使用强制转换(或委托构造函数)明确指定其中一个操作数的类型。