Не могу использовать троичный оператор для назначения выражения Linq - PullRequest
3 голосов
/ 14 декабря 2011

Я только что набрал следующий код:

Expression<Func<ContentItem, bool>> expression = 
                fileTypeGroupID.HasValue ? n => n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value : n => true;

Visual Studio говорит, что не может определить тип n.

Код кажется мне подходящим - он простоиспользование троичного оператора для назначения одного из двух литералов Expression переменной Expression.

Является ли Visual Studio просто недостаточно умным, чтобы вывести тип n внутри троичного оператора, или я сделалкакая-то ошибка?

Ответы [ 3 ]

12 голосов
/ 14 декабря 2011

Этот вопрос задается почти каждый день в той или иной форме.

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

Следствие и альтернатива не содержат информации о том, какой типлямбда должна быть, и поэтому тип условного не может быть выведен.Поэтому нельзя проверить, правильно ли присвоение.

Удовлетворительно подумать, почему язык был разработан таким образом.Предположим, у вас есть перегрузки:

 void M(Func<string, int> f) {}
 void M(Func<double, double> f) {}

и вызов

M( b ? n=>n.Foo() : n => n.Bar() );

Опишите, как разрешение перегрузки определяет, какая перегрузка M выбрана в мире, где типы выводятся снаружи внутрь.

Теперь рассмотрим вот что:

M( b1 ? (b2 ? n=>n.Foo() : n => n.Bar() ) : (b3 ? n=>n.Blah() : n=>n.Abc()) );

Сложнее, не так ли?Теперь представьте, что Foo, Bar, Blah и Abc сами по себе являются методами, которые принимают функции, а также имеют аргументы с условными операторами, содержащими лямбда-выражения.

Мы не хотим усложнять процесс вывода типов без соответствующего огромного преимущества.и нет такой огромной выгоды для условного оператора.

То, что вы должны сделать в вашем случае, - приведение одного или обоих последствий и альтернативы конкретному типу.

2 голосов
/ 14 декабря 2011

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

Expression<Func<ContentItem, bool>> expression = 
  n => !fileTypeGroupID.HasValue || n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value;
1 голос
/ 14 декабря 2011
fileTypeGroupID.HasValue ? (ContentItem n) => n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value
                         : (ContentItem n) => true;

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

...