C # 9 Nullable 형식 문제

Sep 12 2020

다음 (VS 16.8.0 미리보기 2.1 C # 9.0 미리보기) 코드를 고려하세요.

#nullable enable

using System.Collections.Generic;

class Archive<T> where T : notnull 
{
  readonly Dictionary<string, T> Dict = new();

  public T? GetAt(string key) 
  { 
    return Dict.TryGetValue(key, out var value) ? value : default;
  }
}

class Manager 
{
  public int Age { get; set; }
}

class Main34 
{
  long F3() 
  {
    Archive<long> a = new();
    var johnAge = a.GetAt("john");
    if (johnAge is null) return -1; // Error CS0037  Cannot convert null to 'long' because it is a non - nullable value type
    return johnAge; 
  }

  long F4() 
  {
    Archive<Manager> a = new();
    var johnAge = a.GetAt("john");
    //if (johnAge is null) return -1;
    return johnAge.Age; // Correct ! warning "Derefrencing of a possibly null reference" will be removed if line above unremarked 
  }
}

나는, F3에서 오류를 해결 / 힘든 시간을 이해하는 데 문제 것은 컴파일러가 johnAge 생각처럼이 보인다 long하지 long?의 복귀에도 불구하고 (내가 VS에서 유혹에 의해 확인으로) Archive<T>.GetAt존재T?

내가 원하는 일을 할 일반 아카이브를 갖는 방법이 있습니까 (T가 nullable이 아닌 기본 유형, 즉 긴 경우에도 Nullable을 반환하는 GetAt 메서드)?

답변

8 JonSkeet Sep 12 2020 at 15:13

기본적으로 이것은 nullable 값 형식과 nullable 참조 형식이 매우 다르기 때문입니다. CLR은 nullable 값 형식을 인식하지만 CLR에 관한 한 nullable 참조 형식은 "일반 참조 형식이며 컴파일러에 nullable로 간주해야하는지 여부를 알려주는 특성이 있습니다."

때 T이 notnull제약 조건을, 유형 T?단지로 컴파일 T일리노이한다. 제약 조건 이 값 유형 Nullable<T>이기 때문에로 컴파일 할 수 없습니다 .Nullable<T>T

그래서 대한 Archive<long>의 GetAt키를 사전에 발견되지 않는 경우 방법은 0L를 반환합니다 - 그것은 하지 않습니다 (그리고 수 있음)의 NULL 값을 반환 Nullable<long>에 코드가 무엇을, F3효율적으로 기대된다.

전체 "nullable reference types"기능은 기본적으로없는 형식 시스템에 nullable 인식의 "베니어"를 추가하려는 시도로 인해 어려움을 겪습니다. 새로운 런타임과 언어가 지금 처음부터 함께 설계 되었다면이를 더 밀접하게 통합하려고 할 것입니다. 그대로, 나는 기능은 여전히 많은 가치를 가지고 있다고 생각합니다 -하지만 그것은 확실히 일을하게 정말 이 제네릭에 관해서 까다로운.