IEnumerable이 null인지 또는 비어 있는지 확인하는 방법은 무엇입니까?


154

나는 string.IsNullOrEmpty방법을 좋아한다 . IEnumerable에 대해 동일한 기능을 허용하는 것을 갖고 싶습니다. 그런가요? 어쩌면 컬렉션 도우미 클래스일까요? 내가 묻는 이유는 if성명서에서 후두둑이 인 경우 코드가 복잡해 보이기 때문입니다 (mylist != null && mylist.Any()). 갖는 것이 훨씬 더 깨끗합니다 Foo.IsAny(myList).

이 게시물은 그 대답을 제공하지 않습니다 : IEnumerable이 비어 있습니까? .


1
@ msarchet : 이것이 의견이 아닌 경우 아마 당신에게 대답을 줄 것입니다 :)
Schultz9999

나에게 이것은 일종의 XY 문제처럼 보입니다. "어떻게 귀찮게하지 않고 어디서나 null을 정확하게 검사 할 수 있는가?"라는 질문 대신 "어디서나 null을 검사하지 않도록 디자인을 개선 할 수 있는가?"
sara

나는 그것을 중복을 고려하지 않을 수 있도록 @nawfal, 당신이에 연결된 질문은 구체적으로 널 (null) 검사를 포함하지 않습니다
Mygeen

답변:


188

확실히 당신 그것을 쓸 수 있습니다 :

public static class Utils {
    public static bool IsAny<T>(this IEnumerable<T> data) {
        return data != null && data.Any();
    }
}

그러나 모든 서열이 반복 가능한 것은 아님을주의해야한다. 일반적으로 나는 만일을 위해 그들을 한 번만 걷는 것을 선호합니다.


12
이것이 좋은 패턴입니까? 나는 그것을 떨어 뜨릴 것이다 this– 나는 null추악한 디자인의 표시로 불려지는 확장 방법을 고려한다 .
Mormegil

28
@Mormegil 왜? 확장 메소드는 결국 C #에게 널 (null)을 처리 할 수있는 기능을 제공하는데, 루비와 같은 다른 언어는 당연히 받아들입니다.
Matt Greer

5
이것이 반드시 나쁜 이유는 무엇 입니까? 이 경우와 같이, 더 균질하게 처리하고 특별한 경우를 줄이면서 매우 편리합니다.
Mr. Putty

5
@ Mormegil meh-나는 그것에 대해 흥분 할 수 없습니다. 의도가 분명한 한
Marc Gravell

6
@Miryafa .Any()IEnumerable<T>(또는 IQueryable<T>다른 시나리오이지만) 에서 작동하는 확장 방법입니다 . 그렇게하면 적어도 부분적으로 (아직 소비되고 있음을 의미하지만) 시퀀스를 소비합니다. 단 하나의 요소 만 읽으면됩니다 (특히 술어가없는 경우). 따라서 시퀀스 ( IEnumerable<T>)를 반복 할 필요가 없으므로 그럴 수도 있습니다 . Any()술어없이 본질적으로 동등 foreach(var x in sequence) { return true; } return false;-이 사용되지만 GetEnumerator()대신 컴파일러 구문 등
마크 Gravell

119
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
    return enumerable == null || !enumerable.Any();
}

8
글쎄요, OP는 IEnumerable <T> ;-)이 아니라 IEnumerable을 요청했습니다
yoyo

8
예, 확장명 IEnumerable이 없습니다 Any().
Blaise

23

다음은 정적 래퍼 클래스를 포함하는 @Matt Greer의 유용한 답변의 수정 된 버전입니다.이를 복사하여 새 소스 파일에 붙여 넣을 수 있으며 Linq에 의존하지 않고 일반적인 IEnumerable<T>오버로드를 추가하여 값 유형의 권투를 피할 수 있습니다 제네릭이 아닌 버전에서 발생합니다. [편집 : 참고를 사용한다고 IEnumerable<T>해서 열거 자의 복싱을 막을 수는 없으며 , 오리 타이핑으로이를 막을 수는 없지만 최소한 값 유형 컬렉션의 요소는 각각 복싱되지는 않습니다.]

using System.Collections;
using System.Collections.Generic;

public static class IsNullOrEmptyExtension
{
    public static bool IsNullOrEmpty(this IEnumerable source)
    {
        if (source != null)
        {
            foreach (object obj in source)
            {
                return false;
            }
        }
        return true;
    }

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
    {
        if (source != null)
        {
            foreach (T obj in source)
            {
                return false;
            }
        }
        return true;
    }
}

15

또 다른 방법은 열거자를 가져와 MoveNext () 메서드를 호출하여 항목이 있는지 확인하는 것입니다.

if (mylist != null && mylist.GetEnumerator().MoveNext())
{
    // The list is not null or empty
}

이것은 IEnumerable 및 IEnumerable <T>에서도 작동합니다.


4
이 열거 자에 대해 dispose를 호출해야합니까? 컬렉션이 멀티 스레딩을 인식하는 경우? 예. stackoverflow.com/questions/13459447/…
TamusJRoyce

2
@TamusJRoyce IEnumerable<T>제네릭 IEnumerable이 아닌 구현은 구현하지 않기 때문에 귀하의 진술은에 대해서만 사실입니다 IDisposable.
이안 켐

9

최신 C # 기능을 활용하여 내가하는 방식 :

옵션 1)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any() ?? false);
    }
}

옵션 2)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any()).GetValueOrDefault();
    }
}

그리고 컬렉션이 비어 있는지 확인 Count == 0하거나 Count() == 0확인 하지 마십시오 . 항상 Linq를 사용하십시오.Any()


2
Count == 0은 괜찮습니다 .... 아마도 Any ()보다 빠를까요? 그러나 Count () == 0이 잘못되었습니다. Count ()가 전체 컬렉션을 반복하여 궁금해하는 사람들에게는 엄청난 양의 오버 헤드가 추가 될 수 있습니다!
Anthony Nichols

Count ()는 ICollection으로 캐스팅 할 수없는 경우에만 열거를 반복합니다. 즉,이 메서드를 호출 할 때 개체에 Count 속성이 이미 있으면 해당 속성 만 반환하고 성능은 동일해야합니다. 여기 구현을 체크 아웃 : referencesource.microsoft.com/#System.Core/System/Linq/...
로널드 레이

IEnumerable을 사용하는 경우 Linq 구현이 전체 컬렉션을 반복하고 Any는 반복자를 한 번만 이동하므로 Count ()를 사용하여 비어 있는지 테스트하는 것은 확실히 나쁜 생각입니다. Count 속성은 IEnumerable 인터페이스의 일부가 아니므로이 경우 Count 속성을 사용할 수 없습니다. 그렇기 때문에 Any ()를 사용하여 모든 시나리오에서 공허함을 테스트하는 것이 항상 더 나은 아이디어라고 생각합니다.
Ronald Rey

읽을 수없는 부정 연산자 !가 특히 두 번째 옵션 인 방법에 대한 좋은 예입니다 .)
Fabio

6

도움이 될 수 있습니다

public static bool IsAny<T>(this IEnumerable<T> enumerable)
{
    return enumerable?.Any() == true;
}

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
    return enumerable?.Any() != true;
}

5

C # 6부터는 null 전파를 사용할 수 있습니다 .myList?.Any() == true

그래도 너무 애매하거나 확장 방법을 선호한다면 Matt Greer와 Marc Gravell의 답변을 추천하지만 완벽 함을 위해 약간의 확장 기능이 있습니다.

그들의 답변은 동일한 기본 기능을 제공하지만 각각 다른 관점에서 볼 수 있습니다. Matt의 대답은- string.IsNullOrEmpty정직성을 사용하는 반면 Marc의 대답은 Linq의 .Any()길을 따라 작업을 완료합니다.

개인적으로 .Any()도로 를 사용하는 경향이 있지만 방법의 다른 과부하 에서 상태 확인 기능을 추가하고 싶습니다 .

    public static bool AnyNotNull<T>(this IEnumerable<T> source, Func<T, bool> predicate = null)
    {
        if (source == null) return false;
        return predicate == null
            ? source.Any()
            : source.Any(predicate);
    }

따라서 여전히 다음과 같은 일 myList.AnyNotNull(item=>item.AnswerToLife == 42);을 할 수 .Any()있습니다.

C # 6 방법 을 사용 하면 null 대신 전파 하는 실제 효과 인 myList?.Any()a bool?대신을 반환합니다.bool


1
collection? .Any ()의 문제점은 전 이적이지 않다는 것입니다. null 인 경우 collection? .Any () == true는 false이지만 collection? .Any () == false도 false입니다. 또한! collection? .Any () == false도 false입니다.
Jakub Szułakiewicz

4
if (collection?.Any() == true){
    // if collection contains more than one item
}
if (collection?.Any() != true){
    // if collection is null
    // if collection does not contain any item
}

2

다음은 Marc Gravell 's answer 의 코드 와 사용 예입니다.

using System;
using System.Collections.Generic;
using System.Linq;

public static class Utils
{
    public static bool IsAny<T>(this IEnumerable<T> data)
    {
        return data != null && data.Any();
    }
}

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        if (items.IsAny())
        {
            foreach (var item in items)
            {
                Console.WriteLine(item);
            }
        }
        else
        {
            Console.WriteLine("No items.");
        }
    }
}

그가 말했듯이 모든 시퀀스가 ​​반복 가능한 것은 아니므로 시퀀스를 IsAny()단계별로 시작 하기 때문에 코드가 때때로 문제를 일으킬 수 있습니다 . 나는 무엇을 의심 로버트 하비의 대답 의미는 자주 확인하지 않아도했다 null 비 웁니다. 종종 null을 확인한 다음을 사용할 수 있습니다 foreach.

시퀀스를 두 번 시작하지 않고를 활용하기 위해 foreach다음과 같은 코드를 작성했습니다.

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        bool isEmpty = true;
        if (items != null)
        {
            foreach (var item in items)
            {
                isEmpty = false;
                Console.WriteLine(item);
            }
        }
        if (isEmpty)
        {
            Console.WriteLine("No items.");
        }
    }
}

확장 방법을 사용하면 두 줄의 입력 줄을 절약 할 수 있지만이 코드는 더 명확 해 보입니다. 일부 개발자는 이것이 IsAny(items)실제로 시퀀스를 단계별로 시작 한다는 것을 즉시 인식하지 못할 것이라고 생각합니다 . (물론 많은 시퀀스를 사용하는 경우 시퀀스를 통해 어떤 단계를 거치는 지 생각하는 법을 빨리 배우게됩니다.)


null로 IsAny를 호출하면 예외가 발생합니다
Ace Trajkov

3
@Ace를 사용해 보셨습니까? 예외가 발생하는 것처럼 보이지만 null 인스턴스에서 확장 메서드를 호출 할 수 있습니다 .
돈 커크비

2

사용 Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false);합니다. 도움이 되었기를 바랍니다.

고장:

Collection?.Any()nullCollection이 null이고 falseCollection이 비어 있으면 반환 됩니다 .

Collection?.Any()??falsefalseCollection이 비어 있고 Collection이이면 우리에게 줄 것 false입니다 null.

그것의 보완은 우리에게 줄 것이다 IsEmptyOrNull.


2

Jon Skeet의 답변 ( https://stackoverflow.com/a/28904021/8207463 )에는 NULL 및 EMPTY에 Extension Method-Any ()를 사용하는 것이 좋습니다. 그러나 그는 NOT NULL의 경우 질문 소유자의 유효성을 검사합니다. 따라서 AS NULL의 유효성을 검사하도록 Jon의 접근 방식을 신중하게 변경하여 다음을 수행하십시오.

If (yourList?.Any() != true) 
{
     ..your code...
}

사용하지 마십시오 (AS NULL의 유효성을 검사하지 않음).

If (yourList?.Any() == false) 
{
     ..your code...
}

AS NOT NULL의 유효성을 검사하는 경우 (예를 들어 테스트하지 않았지만 컴파일러 오류없이) 술어를 사용하는 것과 같은 작업을 수행 할 수 있습니다.

If (yourList?.Any(p => p.anyItem == null) == true) 
{
     ..your code...
}

https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,8788153112b7ffd0

사용할 수있는 .NET 버전은 다음을 확인하십시오.

https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=netframework-4.8#moniker-applies-to


1

나는 같은 문제가 있었고 다음과 같이 해결했다.

    public bool HasMember(IEnumerable<TEntity> Dataset)
    {
        return Dataset != null && Dataset.Any(c=>c!=null);
    }

"c => c! = null"은 모든 null 엔터티를 무시합니다.


1

@Matt Greer답변에서 이것을 만들었습니다.

그는 OP의 질문에 완벽하게 대답했다.

나는 null을 확인하면서 Any의 원래 기능을 유지하면서 이와 같은 것을 원했습니다. 다른 사람이 비슷한 것을 필요로 할 경우를 대비하여 이것을 게시하고 있습니다.

특히 나는 여전히 술어를 전달할 수 있기를 원했습니다.

public static class Utilities
{
    /// <summary>
    /// Determines whether a sequence has a value and contains any elements.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="source">The <see cref="System.Collections.Generic.IEnumerable"/> to check for emptiness.</param>
    /// <returns>true if the source sequence is not null and contains any elements; otherwise, false.</returns>
    public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
    {
        return source?.Any() == true;
    }

    /// <summary>
    /// Determines whether a sequence has a value and any element of a sequence satisfies a condition.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="source">An <see cref="System.Collections.Generic.IEnumerable"/> whose elements to apply the predicate to.</param>
    /// <param name="predicate">A function to test each element for a condition.</param>
    /// <returns>true if the source sequence is not null and any elements in the source sequence pass the test in the specified predicate; otherwise, false.</returns>
    public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
        return source?.Any(predicate) == true;
    }
}

확장 방법의 이름이 더 좋을 수 있습니다.


0

비어 있는지 아닌지 확인하는 다른 최상의 해결책은 무엇입니까?

for(var item in listEnumerable)
{
 var count=item.Length;
  if(count>0)
  {
         // not empty or null
   }
  else
  {
       // empty
  }
}

1
listEnumerablenull 인 경우에는 작동하지 않습니다 . 이는
당면한

0

나는 이것을 사용한다 :

    public static bool IsNotEmpty(this ICollection elements)
    {
        return elements != null && elements.Count > 0;
    }

에젬 :

List<string> Things = null;
if (Things.IsNotEmpty())
{
    //replaces ->  if (Things != null && Things.Count > 0) 
}

0

한 번 읽은 후에 일부 리소스가 소진되었으므로 전통적인 분리 검사 대신 검사와 읽기를 결합하여 읽지 않는 이유를 생각했습니다.

먼저 널 (null) 체크 인라인 확장을위한 하나가 있습니다.

public static System.Collections.Generic.IEnumerable<T> ThrowOnNull<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null) => source ?? throw new System.ArgumentNullException(paramName ?? nameof(source));

var first = source.ThrowOnNull().First();

그런 다음 우리는 null-and-empty 인라인 확장에 대해 조금 더 관여합니다 (적어도 내가 쓴 방식).

public static System.Collections.Generic.IEnumerable<T> ThrowOnNullOrEmpty<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null)
{
  using (var e = source.ThrowOnNull(paramName).GetEnumerator())
  {
    if (!e.MoveNext())
    {
      throw new System.ArgumentException(@"The sequence is empty.", paramName ?? nameof(source));
    }

    do
    {
      yield return e.Current;
    }
    while (e.MoveNext());
  }
}

var first = source.ThrowOnNullOrEmpty().First();

물론 통화 체인을 계속하지 않고도 둘 다 통화 할 수 있습니다. 또한 paramName을 포함 시켰으므로, "nameof (target)"과 같이 "소스"를 확인하지 않은 경우 호출자가 오류에 대한 대체 이름을 포함 할 수 있습니다.


0
 public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
    {
        return source != null && source.Any();
    }

Not null and Any를 확인하는 내 확장 방법


0

사용자 정의 헬퍼없이 나도 추천 ?.Any() ?? false또는 ?.Any() == true상대적으로 간결하고 한 번만 순서를 지정해야하는.


누락 된 컬렉션을 빈 컬렉션처럼 취급하려면 다음 확장 방법을 사용합니다.

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

이 함수는 모든 LINQ 메소드와 결합 할 수 있으며 foreach, 이뿐 만 아니라 .Any()사람들이 여기에서 제안하는보다 전문화 된 도우미 함수보다이 함수를 선호합니다.


0

나는 사용한다

    list.Where (r=>r.value == value).DefaultIfEmpty().First()

일치하지 않으면 결과는 null이고 그렇지 않으면 개체 중 하나를 반환합니다.

목록을 원한다면 First ()를 떠나거나 ToList ()를 호출하면 목록 또는 null이 제공됩니다.



-1

using System.Linq에서 사용 가능한 메소드에 액세스하려고 할 때 발생하는 마법을 추가 하고 확인하십시오 IEnumerable. 이것을 추가하면 그처럼 Count()단순한 이름의 메소드에 액세스 할 수 있습니다 . 그냥 null value전화하기 전에 확인해야합니다 count():)


-1

확인하면 간단하게 사용했습니다.

내 솔루션을 확인하십시오

foreach (Pet pet in v.Pets)
{
    if (pet == null)
    {
        Console.WriteLine(" No pet");// enumerator is empty
        break;
    }
    Console.WriteLine("  {0}", pet.Name);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.