Условный оператор и делегат сравнения - PullRequest
5 голосов
/ 28 февраля 2012

Учитывая две реализации методов сравнения:

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

7 голосов
/ 28 февраля 2012

Метод ошибок на самом деле говорит сам за себя, но не совсем интуитивно.Если вы используете имя метода без вызова метода, вы обрабатываете группу методов .«Группа», поскольку метод может быть перегружен, а имя может указывать на любой из перегруженных методов.

Теперь группы методов неявно преобразуются в делегат с соответствующей сигнатурой, поэтому ваше назначение в ifработает.

Пока все хорошо.Однако условному оператору ?: необходимо вывести общий тип, в который его второй и третий аргументы могут быть неявно преобразованы, и он не учитывает все преобразования для этого (это может иметь различные проблемы).Он просто смотрит, имеют ли оба аргумента один и тот же тип или один неявно преобразуется в другой.

Это не тот случай: хотя оба аргумента являются группами методов, на самом деле они отличаются групп методов с различными типами, и вы не можете преобразовать одну группу методов в другую.Даже если оба легко могут быть преобразованы в делегат, компилятор запрещает это использование.

То же самое верно и для других типов, кстати:

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

также не удается скомпилировать, длята же причина.И снова, мы можем сделать эту компиляцию, явно приведя любой из аргументов к общему базовому типу:

object = someBool ? (object) "" : New List<Integer>();
3 голосов
/ 28 февраля 2012

Если у вас есть выражение, подобное вашему CompareByKey, оно не имеет какого-либо определенного типа .Net, но имеет специальный тип «группа методов». Это потому, что у вас может быть несколько методов с именем CompareByKey, и неясно, какой из них вам нужен (и он работает точно так же, даже если у вас есть только один метод). Также неясно, какой тип делегата вы хотите, например, Comparison<KeyValuePair<int, string>> или Func<KeyValuePair<int, string>, int>.

Что вы можете сделать с группами методов? Вы можете использовать их для явного создания делегата (new Comparison<KeyValuePair<int, string>>(CompareByKey)), и они также неявно преобразуются в делегаты. Вот почему ваша if версия работает.

Итак, какое это имеет отношение к вашей проблеме? Когда у вас есть условный оператор, компилятор должен выяснить тип всего выражения, и он не может использовать тип переменной, которой вы его назначаете (это не так, как вывод типа работает в C #). И поскольку оба выражения являются группами методов, а группы методов рассматриваются как разные типы без каких-либо неявных преобразований между собой, тип всего выражения определить невозможно. Вот почему вы получаете ошибку.

Вы уже нашли исправление: либо не используйте условный оператор, либо явно указывайте тип одного из операндов, используя приведение (или конструктор делегата).

...