条件运算符和比较委托

本文关键字:比较 条件运算符 | 更新日期: 2023-09-27 18:26:07

给定比较方法的两个实现:

// 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;

(在上面的任务中都很好,当铸造时,即使铸造只是在真正的零件上)

条件运算符和比较委托

错误方法实际上说明了这一切,但它不是很直观。如果在不调用方法的情况下使用方法名称,则处理的是方法组。"group",因为方法可能被重载,并且名称可以指示任何重载的方法。

现在,方法组可以隐式转换为具有匹配签名的委托,这就是if中的赋值有效的原因。

到目前为止,一切都很好。然而,条件运算符?:需要推导出一个公共类型,它的第二个和第三个参数可以隐式转换为该类型,并且它没有考虑所有的转换(这会有不同的问题)。它只是查看两个参数是否具有相同的类型,或者其中一个参数是否可以隐式转换为另一个参数。

这里的情况并非如此:尽管两个参数都是方法组,但它们实际上是不同的方法组,具有不同的类型,并且您无法将一个方法组转换为另一个。即使两者都可以很容易地转换为委托,编译器也禁止这种用法。

顺便说一句,其他类型也是如此:

object = someBool ? "" : New List<Integer>();

由于同样的原因,也无法编译。同样,我们可以通过显式地将其中一个参数强制转换为一个公共的基类型来进行编译:

object = someBool ? (object) "" : New List<Integer>();

如果有一个像CompareByKey这样的表达式,它没有任何特定的.Net类型,而是有一个特殊的类型"方法组"。这是因为你可以有几个名为CompareByKey的方法,但不清楚你想要哪一个(即使你只有一个方法,它的工作原理也完全一样)。此外,还不清楚您想要什么委托类型,例如Comparison<KeyValuePair<int, string>>Func<KeyValuePair<int, string>, int>

你能用方法组做什么?您可以使用它们显式创建委托(new Comparison<KeyValuePair<int, string>>(CompareByKey)),它们也可以隐式转换为委托。这就是您的if版本工作的原因。

那么,这和你的问题有什么关系呢?当你有一个条件运算符时,编译器必须计算出整个表达式的类型,并且它不能使用你赋予它的变量的类型(这不是C#中类型推理的工作方式)。由于这两个表达式都是方法组,并且方法组被视为不同的类型,彼此之间没有隐式转换,因此无法确定整个表达式的类型。这就是为什么你会出现错误。

您已经找到了一个修复方法:要么不使用条件运算符,要么使用强制转换(或委托构造函数)显式指定其中一个操作数的类型。