条件运算符和比较委托

时间:2012-02-28 19:26:04

标签: c# .net visual-studio ternary-operator conditional-operator

给出两种比较方法的实现:

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

(在上面的任务中都很好,即使施法只是在真正的部分施放时)

2 个答案:

答案 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#中的工作方式)。并且由于两个表达式都是方法组,并且方法组被视为不同类型,彼此之间没有隐式转换,因此无法确定整个表达式的类型。这就是你得到错误的原因。

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