2010-02-04 4 views
5

Ниже приведен пример тестового кода linqpad. Когда это вызывает ошибки, потому что второй экземпляр «item» имеет нулевой список подэлементов, а не пустой список.Как обращаться с нулевыми списками, такими как пустые списки в linq?

Я хочу обрабатывать обе ситуации (нулевой или пустой список) точно так же, но я задавался вопросом, был ли более чистый способ, чем просто поместить нулевую проверку в список и инициализировать пустой список, когда есть нуль.

другими словами, я мог бы сделать это:

from si in (i.subitems == null ? new List<item>() : i.subitems) 

, но это немного некрасиво, и я задавался вопросом, как я могу улучшить это?

public class item 
{ 
    public string itemname { get; set; } 
    public List<item> subitems { get; set; } 
} 

void Main() 
{ 
    List<item> myItemList = new List<item>() 
    { 
     new item 
     { 
      itemname = "item1", 
      subitems = new List<item>() 
      { 
       new item { itemname = "subitem1" }, 
       new item { itemname = "subitem2" } 
      } 
     }, 
     new item 
     { 
      itemname = "item2" 
     } 
    }; 

    myItemList.Dump(); 

    var res = (from i in myItemList 
      from si in i.subitems 
      select new {i.itemname, subitemname = si.itemname}).ToList(); 

    res.Dump(); 
} 

в качестве бонуса вопрос, может это тот же запрос LINQ можно представить в виде лямбда и лечения NULLS таким же образом?

Приветствия, Крис

ответ

13

Вы можете использовать null coalescing operator

var res = (from i in myItemList 
      from si in i.subitems ?? new List<item>() 
      select new { i.itemname, subitemname = si.itemname }).ToList(); 

Но я думаю, вы должны просто отфильтровать пустые из

var res = (from i in myItemList 
      where i.subitems != null 
      from si in i.subitems 
      select new { i.itemname, subitemname = si.itemname }).ToList(); 

Что касается лямбда-версии, вы можете сказать

var res = myItemList.Where(x => x.subitems != null) 
        .SelectMany(
         x => x.subitems.Select(
          y => new { x.itemname, subitemname = y.itemname } 
         ) 
        ); 

Но версия синтаксиса запроса более читаема.

+0

фактически этот второй вариант очень читабельен и не означает, что новый список должен быть создан только для игнорирования. спасибо –

+0

@ Крис Симпсон: Я добавил версию лямбды, так как вы просили ее.Версия синтаксиса запроса является более читаемой. – jason

+1

Я действительно думаю, что предложение where является самым чистым решением здесь, поэтому я отмечаю это как ответ. Мне просто было интересно узнать об эквиваленте лямбда, но я согласен, это не так понятно. Благодарю. –

11
from si in (i.subitems ?? new List<item>()) 

как об этом?

+1

да, это лучше, чем у меня (и я ногами себя не делать это в первую очередь), но она по-прежнему означает создание объект просто для его устранения, который чувствует себя плохо –

+0

Бонусные баллы за то, что нашли хорошее применение для ?? – captncraig

+0

@captncraig Для других целей, см. Http://stackoverflow.com/questions/1689530/how-useful-is-cs-operator/1689544#1689544 –

8

Вы можете добавить (зло) метод расширения, чтобы сделать работу для вас

public static IEnumerable<T> EnsureNotEmpty<T>(this IEnumerable<T> enumerable) { 
    if (enumerable == null) { 
    return Enumerable.Empty<T>(); 
    } else { 
    return enumerable; 
    } 
} 
+0

Является ли 'Enumerable.Repeat (0)' предпочтительнее ' Enumerable.Empty () '? – bdukes

+0

@bdukes, Enumerable.Empty лучше, поскольку это более декларативно из ваших намерений. По какой-то причине, хотя я продолжаю забывать, что это часть фреймворка и вместо этого повторяю (0). – JaredPar

+4

Метод следует называть 'EnsureNotNull (...)'. Поскольку 'EnsureNotEmpty (...)' похоже, что это добавит намеренный элемент. : -> – herzmeister

0

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

Это, конечно, предполагает, что у вас есть доступ к изменению элемента.

Нулевая оператор коалесцирующий является то, что вы ищете, как отметил Хантер Дейли

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

  • Нет связанных вопросов^_^