programing

왜 그럴까요?수집이 null인 경우 각 루프 스로우 NullRefException에 대한 NET?

sourcejob 2023. 5. 9. 22:38
반응형

왜 그럴까요?수집이 null인 경우 각 루프 스로우 NullRefException에 대한 NET?

그래서 이런 상황에 자주 부딪히곤 합니다.어디에Do.Something(...)다음과 같은 null 컬렉션을 반환합니다.

int[] returnArray = Do.Something(...);

그런 다음 이 컬렉션을 다음과 같이 사용하려고 합니다.

foreach (int i in returnArray)
{
    // do some more stuff
}

그냥 궁금해서 그러는데, 왜 각 루프는 null 컬렉션에서 작동할 수 없나요?0번의 반복이 null 컬렉션으로 실행되는 것이 논리적으로 보입니다.대신 그것은 a를 던집니다.NullReferenceException왜 이럴 수 있는지 아는 사람?

정확히 무엇이 반환되는지 명확하지 않은 API로 작업하고 있기 때문에 짜증이 납니다.if (someCollection != null)온통.

짧은 대답은 "그것이 컴파일러 설계자들이 설계한 방식이기 때문입니다." 하지만 현실적으로, 여러분의 컬렉션 개체는 null입니다. 그래서 컴파일러가 열거자가 컬렉션을 순환하도록 할 수 있는 방법은 없습니다.

이와 같은 작업을 수행해야 하는 경우 null 병합 연산자를 사용해 보십시오.

int[] array = null;

foreach (int i in array ?? Enumerable.Empty<int>())
{
   System.Console.WriteLine(string.Format("{0}", i));
}

A foreach루프가 호출합니다.GetEnumerator방법.
컬렉션이 다음과 같은 경우null이 메서드 호출은 다음과 같은 결과를 낳습니다.NullReferenceException.

a를 반환하는 것은 나쁜 관행입니다.null컬렉션입니다. 대신 메서드가 빈 컬렉션을 반환해야 합니다.

빈 컬렉션과 컬렉션에 대한 null 참조 사이에는 큰 차이가 있습니다.

사용할 때foreach내부적으로는 IEnumberable의 GetEnumerator() 메서드를 호출합니다.참조가 null인 경우 이 예외가 발생합니다.

그러나 비어 있는 것은 완벽하게 유효합니다.IEnumerable또는IEnumerable<T>이 경우 컬렉션이 비어 있기 때문에 각각은 어떤 것에도 대해 "반복"하지 않지만 완전히 유효한 시나리오이기 때문에 던지지도 않습니다.


편집:

개인적으로 이 문제를 해결해야 한다면 확장 방법을 추천합니다.

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

그런 다음 전화하면 됩니다.

foreach (int i in returnArray.AsNotNull())
{
    // do some more stuff
}

오래 전에 답변을 드리고 있지만, 저는 Null 포인터 예외를 피하기 위해 다음 방법으로 이 작업을 시도했으며 C# Null 검사 연산자를 사용하는 사람에게 유용할 수 있습니다.

     //fragments is a list which can be null
     fragments?.ForEach((obj) =>
        {
            //do something with obj
        });

이 문제를 해결하기 위한 또 다른 확장 방법:

public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
{
    if(items == null) return;
    foreach (var item in items) action(item);
}

다양한 방법으로 소비:

을 받아들이는 방법으로.T:

returnArray.ForEach(Console.WriteLine);

다음과 같은 표정으로:

returnArray.ForEach(i => UpdateStatus(string.Format("{0}% complete", i)));

다중 행 익명 방식으로

int toCompare = 10;
returnArray.ForEach(i =>
{
    var thisInt = i;
    var next = i++;
    if(next > 10) Console.WriteLine("Match: {0}", i);
});

null 컬렉션은 빈 컬렉션과 동일하지 않기 때문입니다.빈 컬렉션은 요소가 없는 컬렉션 개체이고 null 컬렉션은 존재하지 않는 개체입니다.

여기 시도해 볼 것이 있습니다. 어떤 종류의 컬렉션이든 두 개의 컬렉션을 선언합니다., 하나는 합니다.null그런 다음 두 컬렉션에 개체를 추가하고 어떻게 되는지 확인합니다.

확장 방법을 작성하면 다음과 같은 이점이 있습니다.

public static class Extensions
{
   public static void ForEachWithNull<T>(this IEnumerable<T> source, Action<T> action)
   {
      if(source == null)
      {
         return;
      }

      foreach(var item in source)
      {
         action(item);
      }
   }
}

은 의잘니의 입니다.Do.Something()여기서 가장 좋은 방법은 null이 아닌 0 크기의 배열을 반환하는 것입니다.

에서 왜하면뒤는서에냐는▁the▁the▁because.foreach다음에 해당하는 열거자를 가져옵니다.

using (IEnumerator<int> enumerator = returnArray.getEnumerator()) {
    while (enumerator.MoveNext()) {
        int i = enumerator.Current;
        // do some more stuff
    }
}

예외가 발생하는 이유에 대한 설명은 여기에 제공된 답변과 함께 매우 명확하다고 생각합니다.저는 이 컬렉션들로 제가 평소에 작업하는 방식을 보완하고 싶습니다.때때로 컬렉션을 한 번 이상 사용하고 매번 Null 여부를 테스트해야 하기 때문입니다.이를 방지하기 위해 다음을 수행합니다.

    var returnArray = DoSomething() ?? Enumerable.Empty<int>();

    foreach (int i in returnArray)
    {
        // do some more stuff
    }

이렇게 하면 예외를 두려워하지 않고 원하는 만큼 컬렉션을 사용할 수 있으며 과도한 조건문으로 코드를 오염시키지 않습니다.

연산자 null 하기 null - " " " 입니다.?.또한 훌륭한 접근 방식입니다.그러나 어레이의 경우(문제의 예와 같이) 다음과 같이 목록으로 변환해야 합니다.

    int[] returnArray = DoSomething();

    returnArray?.ToList().ForEach((i) =>
    {
        // do some more stuff
    });
SPListItem item;
DataRow dr = datatable.NewRow();

dr["ID"] = (!Object.Equals(item["ID"], null)) ? item["ID"].ToString() : string.Empty;

언급URL : https://stackoverflow.com/questions/3088147/why-does-net-foreach-loop-throw-nullrefexception-when-collection-is-null

반응형