2010-09-22 4 views
6

я имел следующее заявление, которое всегда возвращает нуль:Почему Null недопустимая проекция LINQ?

var addins = allocations.SelectMany(
     set => set.locations.Any(q => q.IsMatch(level, count)) 
     ? (List<string>)set.addins : null 
    ); 

я изменил его немного, и теперь он работает отлично:

var addins = allocations.SelectMany(
     set => set.locations.Any(q => q.IsMatch(level, count)) 
     ? set.addins : new List<string>() 
    ); 

Мой основной вопрос: Почему не нулевой служить тип возврата от тернарного оператора в этом контексте LINQ?

Второй вопрос: есть ли более умный способ сформулировать вышеуказанный запрос (особенно если он устраняет «новый список()»)?

ответ

11

Enumerable.SelectMany будет пытаться перечислить по последовательности, возвращаемой вашего лямбда, и он бросает NullReferenceException пытается вызвать GetEnumerator() на нуль. Вам нужно предоставить фактическую пустую последовательность. Вместо того, чтобы создать новый список, вы можете использовать Enumerable.Empty:

var addins = allocations.SelectMany(
    set => set.locations.Any(q => q.IsMatch(level, count)) 
    ? (List<string>)set.addins : Enumerable.Empty<string>() 
    ); 

Я подозреваю, что вы на самом деле хотите, чтобы просто позвонить, где раньше SelectMany отфильтровать наборы вы не хотите:

var addins = allocations 
    .Where(set => set.locations.Any(q => q.IsMatch(level, count))) 
    .SelectMany(set => (List<string>)set.addins); 

Или, в синтаксисе запроса:

var addins = 
    from set in allocations 
    where set.locations.Any(q => q.IsMatch(level, count)) 
    from addin in (List<string>)set.addins 
    select addin; 
+1

Отличный ответ и проницательность. Кстати, актеры на «set.addins» не нужны в других примерах, так как троичный оператор не задействован. –

1

сделать что:

(List<string>)set.addins : (List<string>)null

+0

Я уже пытался это сделать. Это ничего не изменило. :( –

Смежные вопросы