C #의 일반 메소드에서 NULL을 어떻게 반환 할 수 있습니까?


546

이 (더미) 코드를 사용하는 일반적인 방법이 있습니다 (예, IList에 술어가 있다는 것을 알고 있습니다.하지만 내 코드는 IList를 사용하지 않지만 다른 컬렉션을 사용합니다. 어쨌든 이것은 질문과 관련이 없습니다 ...)

static T FindThing<T>(IList collection, int id) where T : IThing, new()
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;  // ERROR: Cannot convert null to type parameter 'T' because it could be a value type. Consider using 'default(T)' instead.
}

이것은 나에게 빌드 오류를 준다

"값 유형일 수 있으므로 널을 유형 매개 변수 'T'로 변환 할 수 없습니다. 대신 'default (T)'를 사용하는 것이 좋습니다."

이 오류를 피할 수 있습니까?


C # 8의 nullable 참조 유형이 이제 더 나은 솔루션입니까? docs.microsoft.com/en-us/dotnet/csharp/nullable-references 반환 null여부에 관계없이의 T이다 Object또는 intchar.
알렉산더-복원 모니카

답변:


968

두 가지 옵션 :

  • 리턴 은 T가 참조 유형 (또는 널 입력 가능 값 유형), for , for 등인 경우 리턴 함 default(T)을 의미합니다 ( 기본값 테이블 (C # 참조) ).null0int'\0'char
  • T를 where T : class제약 조건 이있는 참조 유형으로 제한 한 다음 null정상적으로 반환

3
반환 유형이 클래스가 아닌 열거 형인 경우 어떻게합니까? 나는 T를 지정할 수 없다 : enum :(
Justin

1
.NET에서 열거 형은 정수 유형을 둘러싼 매우 얇고 누출이 많은 래퍼입니다. 규칙은 "default"열거 형 값에 0을 사용하는 것입니다.
Mike Chamberlain

27
이것에 대한 문제는이 일반적인 방법을 사용하여 데이터베이스 객체를 DbNull에서 Int로 변환하고 T가 int 인 경우 default (T)를 반환하고 0을 반환한다는 것입니다. 실제로 의미가 있다면 해당 필드가 null 인 경우 나쁜 데이터를 전달할 수 있습니다. 또는 더 좋은 예는 DateTime입니다. 필드가 "DateClosed"와 같고 계정이 여전히 열려있어 null로 반환 된 경우 실제로는 기본적으로 (DateTime) 1/1/0000으로 설정되어 컴퓨터가 발명되기 전에 계정이 닫 혔음을 암시합니다.
Sinaesthetic

21
@Sinaesthetic : 따라서 Nullable<int>또는 Nullable<DateTime>대신 변환합니다 . 널 입력 가능하지 않은 유형을 사용하고 널 (NULL) 값을 나타내야하는 경우 문제가 있습니다.
Jon Skeet

1
동의합니다. 내가 한 일이 MyMethod <T> ()와 비슷하다고 생각합니다. 널이 아닌 유형이고 MyMethod <T?> (); 널 입력 가능 유형이라고 가정합니다. 따라서 시나리오에서 임시 변수를 사용하여 null을 잡고 거기에서 벗어날 수 있습니다.
Sinaesthetic

84
return default(T);

이 링크 : msdn.microsoft.com/en-us/library/xwth0h0d(VS.80).aspx 가 그 이유를 설명해야합니다.
Harper Shelby

1
젠장, 나는이 키워드에 대해 알고 있었다면 많은 시간을 절약 할 수 있습니다-감사합니다 Ricardo!
아나 베츠

1
'default'키워드가 더 포괄적 인 솔루션이므로 숫자 유형 및 구조체와 함께 비 참조 유형을 사용할 수 있기 때문에 이것이 더 많은 표를 얻지 못한 것에 놀랐습니다. 수락 된 답변이 문제를 해결하고 실제로 도움이되지만 반환 유형을 nullable / reference 유형으로 제한하는 방법에 더 잘 대답합니다.
Steve Jackson

33

제약 조건을 조정할 수 있습니다.

where T : class

그런 다음 null 반환이 허용됩니다.


감사. 허용되는 솔루션으로 2 개의 답변을 선택할 수 없으므로 John Skeet의 원인에는 2 가지 솔루션이 있습니다.
edosoft

@Migol 그것은 당신의 요구 사항에 따라 다릅니다. 아마도 그들의 프로젝트는 그것을 요구할 것입니다 IDisposable. 예, 대부분의 경우 필요하지 않습니다. 예를 들어 System.String구현하지 않습니다 IDisposable. 응답자는 그 사실을 분명히 했어야하지만 대답이 틀리지는 않습니다. :)
ahwm

@Migol 나는 거기에 IDisposable이있는 이유를 전혀 모른다. 제거되었습니다.
TheSoftwareJedi

13

클래스 제약 조건을 일반 형식의 첫 번째 제약 조건으로 추가하십시오.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()

감사. 허용되는 솔루션으로 2 개의 답변을 선택할 수 없으므로 John Skeet의 답변에는 2 가지 솔루션이 있습니다.
edosoft

7
  1. 객체가 있으면 typecast해야합니다.

    return (T)(object)(employee);
  2. null을 반환해야하는 경우

    return default(T);

안녕하세요 user725388은 첫 번째 옵션 확인하시기 바랍니다
Jogi 조셉 조지

7

다음은 사용할 수있는 두 가지 옵션입니다.

return default(T);

또는

where T : class, IThing
 return null;

6

다른 옵션은 이것을 선언의 끝에 추가하는 것입니다.

    where T : class
    where T: IList

그렇게하면 null을 반환 할 수 있습니다.


두 제약 조건이 동일한 유형 인 경우 유형을 한 번 언급하고와 같이 쉼표를 사용하십시오 where T : class, IList. 다른 유형에 제약 조건이 있으면에서 where와 같이 토큰을 반복합니다 where TFoo : class where TBar : IList.
Jeppe Stig Nielsen

3

TheSoftwareJedi의 솔루션 작동

또한 몇 가지 값과 nullable 유형을 사용하여 보관할 수 있습니다.

static T? FindThing<T>(IList collection, int id) where T : struct, IThing
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;
}

1

오류 및 사용자 default(T)또는을 권장합니다 new T.

해당 경로로 이동하면 코드가 유효한지 확인하기 위해 코드에 비교를 추가해야합니다.

그렇지 않으면 "match found"에 대한 출력 매개 변수를 고려하십시오.


1

Nullable Enum 반환 값에 대한 실제 예는 다음과 같습니다.

public static TEnum? ParseOptional<TEnum>(this string value) where TEnum : struct
{
    return value == null ? (TEnum?)null : (TEnum) Enum.Parse(typeof(TEnum), value);
}

C # 7.3 (2018 년 5 월)부터로 제한 조건을 향상시킬 수 있습니다 where TEnum : struct, Enum. 이렇게하면 호출자가 실수로 열거 형이 아닌 값 유형 (예 : int또는 a DateTime)을 제공하지 않습니다 .
Jeppe Stig Nielsen

0

위에 제시된 2 가지 답변에 대한 다른 대안. 반환 유형을로 변경 object하면을 반환 할 수 null있으며 동시에 null이 아닌 반환을 캐스팅 할 수 있습니다 .

static object FindThing<T>(IList collection, int id)
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return (T) thing;
    }
    return null;  // allowed now
}

단점 : 반환 된 객체 (널이 아닌 경우)를 캐스팅하려면 메서드 호출자가 필요합니다. 이는 복싱-> 성능 저하를 의미합니다. 내가 맞아?
Csharpest

0

완벽을 기하기 위해 다음과 같이 할 수도 있음을 아는 것이 좋습니다.

return default;

그것은 같은 것을 반환 return default(T);


0

나를 위해 그것은 그대로 작동합니다. 문제가 정확히 어디입니까?

public static T FindThing<T>(this IList collection, int id) where T : IThing, new()
{
    foreach (T thing in collection)
    {
        if (thing.Id == id)
            return thing;
        }
    }

    return null; //work
    return (T)null; //work
    return null as T; //work
    return default(T); //work


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