C #에 "Empty List"싱글 톤이 있습니까?


80

C #에서는 LINQ와 IEnumerable을 잘 사용합니다. 그리고 모든 것이 훌륭합니다 (또는 적어도 대부분 그렇습니다).

그러나 대부분의 경우 IEnumerable<X>기본값으로 비어 있어야합니다 . 즉,

for (var x in xs) { ... }

null 검사없이 작동합니다. 이제 이것은 더 큰 맥락에 따라 현재 내가하는 일입니다.

var xs = f() ?? new X[0];              // when xs is assigned, sometimes
for (var x in xs ?? new X[0]) { ... }  // inline, sometimes

이제 위의 내용은 나에게 완벽하게 괜찮지 만, 즉 배열 객체를 만드는 데 "추가 오버 헤드"가 있으면 신경 쓰지 않습니다 . 궁금합니다.

C # /. NET에 "빈 변경 불가능한 IEnumerable / IList"싱글 톤이 있습니까? (그렇지 않더라도 위에서 설명한 사례를 처리하는 "더 나은"방법이 있습니까?)

Java는 제네릭이 다르게 처리되기 때문에 유사한 개념이 C #에서도 작동 할 수 있는지 확실하지 않지만 Collections.EMPTY_LIST"잘 형식화 된"을 통해 불변의 싱글 톤을 가지고 Collections.emptyList<T>()있습니다.

감사.


글쎄, 젠장 :) 이것은 Enumerable / IEnumerable이 아닌 List / IList에 초점을 맞춘 결과입니다. 모두 감사합니다.


2
public static class Array<T> { public static readonly T[] Empty = new T[0]; }다음과 같이 호출 할 수 있습니다 Array<string>.Empty.. 여기 CodeReview에서 그것에 대해 물었습니다 .
Şafak Gür 2013 년

답변:


98

을 찾고 있습니다 Enumerable.Empty<T>().

다른 소식에서 Java 빈 목록은 List 인터페이스가 예외를 발생시키는 목록에 요소를 추가하는 메소드를 노출하기 때문에 짜증납니다.


그것은 매우 유효한 포인트입니다! 아마도 그것은 새로운 SO 질문을 보증합니까?

1
당신은 몇 초 느리고 문서 링크가 없었습니다 * 손가락 흔들림 * ;-) 그러나 svicks 주석에 대한 확장에 동의합니다.

또한 다른 사람들은 더 많은 찬성표를 얻었으므로 우리는 심지어 :) 질문을 게시 할 것이지만 지금 잠자리에들 것이며 질문을 따를 수 없습니다. 직접 게시하지 않으시겠습니까?
Stilgar

32
클래스 메서드가 List(인덱스로 액세스 할 수있는 컬렉션) 을 반환해야 할 수 있기 때문입니다. 사람들은 List읽기 전용 될 수 있습니다. 그리고 때로는 List요소가 0 인 읽기 전용을 반환해야 합니다. 따라서 Collections.emptyList()방법. 구현 된 인터페이스가 메서드가 목록을 반환하도록 지정하기 때문에 빈 Iterable을 반환 할 수 없습니다. 큰 문제는 반환 할 수있는 ImmutableList 인터페이스가 없다는 것입니다. .NET에도 동일한 문제가 있습니다. 어떤 IList것이 든 읽기 전용 일 수 있습니다.
Laurent Bourgault-Roy 2012

6
참고로 모든 배열은 C #에서 IList <correspondingType>이며 새 항목을 추가하려고 할 때도 발생합니다.
Grzenio 2014 년

52

Enumerable.Empty<T>() 바로 그것입니다.


3
음, 정확히는 아닙니다 . :) "목록"이 요청되었으므로 Array.Empty<T>()더 정확합니다 IList<T>. 그것은 또한 만족의 행복한 혜택이 있습니다 IReadOnlyCollection<T>. 물론 a IEnumerable<T> 충분하다면 Enumerable.Empty<T>()완벽하게 맞습니다.
Timo

3
@Timo이 질문과이 질문을 포함한 많은 답변은 대략 3 년 전에 작성 Array.Empty<T>되었습니다. :) 어쨌든 제목에도 불구하고 질문은 a IEnumerable<T>가 목적에 적합 하다는 것을 명시 적으로 명확하게합니다 .
Jon

19

나는 당신이 찾고 있다고 생각합니다 Enumerable.Empty<T>().

목록이 종종 변경 가능하기 때문에 빈 목록 싱글 톤은 그다지 의미가 없습니다.


14

원래 예제에서는 빈 배열을 사용하여 빈 열거 형을 제공합니다. 사용하는 Enumerable.Empty<T>()것이 완벽 하지만 다른 경우가있을 수 있습니다 . 배열 (또는 IList<T>인터페이스)을 사용해야하는 경우 방법을 사용할 수 있습니다.

System.Array.Empty<T>()

불필요한 할당을 피하는 데 도움이됩니다.

참고 / 참조 :


문서가 roslyn 분석기와 일치하지 않음을 지적 해 주셔서 감사합니다. GitHub에서 문제를 해결하기 위해 문제를 제기 한 적이 있습니까?
John Zabroski

10

확장 메서드를 추가하는 것은 null을 처리 할 수있는 능력 덕분에 깨끗한 대안이라고 생각합니다.

  public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> list)
  {
    return list ?? Enumerable.Empty<T>();
  }

  foreach(var x in xs.EmptyIfNull())
  {
    ...
  }

1

Microsoft는 다음과 같이`Any () '를 구현했습니다 ( source ).

public static bool Any<TSource>(this IEnumerable<TSource> source)
{
    if (source == null) throw new ArgumentNullException("source");
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        if (e.MoveNext()) return true;
    }
    return false;
}

를 호출하는 확장 메서드를 작성하는 대신 호출 스택에 호출을 저장하려면 !Any()다음 세 가지 변경을 다시 작성하면됩니다.

public static bool IsEmpty<TSource>(this IEnumerable<TSource> source) //first change (name)
{
    if (source == null) throw new ArgumentNullException("source");
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        if (e.MoveNext()) return false; //second change
    }
    return true; //third change
}

1

Enumerable.Empty<T>()목록과 함께 사용 하면 단점이 있습니다. 당신이 손 경우 Enumerable.Empty<T>목록 생성자에 다음 4 사이즈의 배열을 할당 할 수 있습니다. 그러나 Collection목록 생성자에 빈 을 건네면 할당이 발생하지 않습니다. 따라서 코드 전체에서이 솔루션을 사용하면 IEnumerables 중 하나가 목록을 구성하는 데 사용되어 불필요한 할당이 발생합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.