2010-02-04 4 views
5

다음은 일부 linqpad 테스트 코드입니다. 이것이 실행되면 "item"의 두 번째 인스턴스에 빈 목록이 아닌 하위 항목의 null 목록이 있기 때문에 오류가 발생합니다.linq에서 빈 목록과 같이 null 목록을 어떻게 처리합니까?

정확히 같은 방식으로 두 상황 (null 또는 빈 목록)을 처리하려고하지만 null이있을 때 목록에 null 체크를 넣고 빈 목록을 초기화하는 것보다 더 깨끗한 방법이 있는지 궁금해했습니다.

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 쿼리는 람다로 표현하고 널 (null) 같은 방법으로 치료 될 수 있는가?

건배, 그것에 대해

답변

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

@Chris Simpson : 당신이 요청한 이후로 람다 버전을 추가했습니다.쿼리 구문 버전은보다 쉽게 ​​읽을 수 있습니다. – 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로 허용하지 않을 것입니다. 하위 항목을 빈 목록으로 기본 설정 한 다음 하위 항목 설정자에서 null을 허용하지 않도록 항목 생성자를 만들 수 있습니다.

물론 항목을 수정할 권한이 있다고 가정합니다.

널 병합 연산자는 당신이 찾고있는 헌터 데일리에 의해 지적