nullable 참조 형식

nullable 망각 컨텍스트에서 모든 참조 형식은 null 허용이었습니다. Nullable 참조 형식 은 코드로 인해 런타임이 을 throw System.NullReferenceException할 가능성을 최소화하는 nullable 인식 컨텍스트에서 사용하도록 설정된 기능 그룹을 나타냅니다. Nullable 참조 형식에는 참조 형식을 Nullable로 명시적으로 표시하는 기능을 포함하여 이러한 예외를 방지하는 데 도움이 되는 세 가지 기능이 포함되어 있습니다.

  • 변수를 역참조하기 전에 변수가 null일 수 있는지 여부를 확인하는 정적 흐름 분석이 향상되었습니다.
  • 흐름 분석에서 null-state를 확인하도록 API에 주석을 다는 특성입니다.
  • 개발자가 변수에 대해 의도하는 null-state를 명시적으로 선언하는 데 사용하는 변수 주석입니다.

Null 상태 분석 및 변수 주석은 기본적으로 기존 프로젝트에 대해 사용하지 않도록 설정됩니다. 즉, 모든 참조 형식이 계속 null 허용됨을 의미합니다. .NET 6부터 프로젝트에 대해 기본적으로 활성화됩니다. Nullable 주석 컨텍스트를 선언하여 이러한 기능을 활성화하는 방법에 대한 자세한 내용은 Nullable 컨텍스트를 참조하세요.

이 문서의 나머지 부분에서는 코드가 null 값을 역참조할 수도 있는 경우 이 세 가지 기능 영역이 경고를 생성하는 방법을 설명합니다. 변수를 역참조하는 것은 다음 예와 같이 .(점) 연산자를 사용하여 해당 멤버 중 하나에 액세스하는 것을 의미합니다.

string message = "Hello, World!";
int length = message.Length; // dereferencing "message"

값이 null인 변수를 역참조하면 런타임에서 System.NullReferenceException을 throw합니다.

C#의 Nullable 안전성 학습 모듈에서 이러한 개념을 살펴볼 수도 있습니다.

Null 상태 분석

Null 상태 분석은 참조의 null 상태를 추적합니다. 이 정적 분석은 코드가 null을 역참조할 수도 있는 경우 경고를 내보냅니다. 이러한 경고를 해결하여 런타임에서 System.NullReferenceException을 throw하는 경우를 최소화할 수 있습니다. 컴파일러는 정적 분석을 사용하여 변수의 null-state를 확인합니다. 변수는 not-null 또는 maybe-null입니다. 컴파일러는 다음 두 가지 방법으로 변수가 not-null임을 확인합니다.

  1. 변수에 null이 아닌 것으로 알려진 값이 할당되었습니다.
  2. 변수가 null인지 검사되었으며 해당 검사 이후 수정되지 않음.

컴파일러에서 not-null로 확인되지 않은 변수는 maybe-null로 간주됩니다. 분석에서는 실수로 null 값을 역참조할 수도 있는 상황일 때 경고를 제공합니다. 컴파일러는 null-state를 기반으로 경고를 생성합니다.

  • 변수가 not-null인 경우 해당 변수는 안전하게 역참조될 수 있습니다.
  • 변수가 maybe-null인 경우 해당 변수를 역참조하기 전에 검사하여 변수가 null이 아닌지 확인해야 합니다.

다음 예제를 참조하세요.

string message = null;

// warning: dereference null.
Console.WriteLine($"The length of the message is {message.Length}");

var originalMessage = message;
message = "Hello, World!";

// No warning. Analysis determined "message" is not null.
Console.WriteLine($"The length of the message is {message.Length}");

// warning!
Console.WriteLine(originalMessage.Length);

앞의 예제에서 컴파일러는 첫 번째 메시지가 인쇄될 때 messagemaybe-null임을 확인합니다. 두 번째 메시지에 대한 경고는 없습니다. 마지막 코드 줄은 originalMessage가 null일 수 있으므로 경고를 생성합니다. 다음 예는 노드 트리를 루트로 트래버스하고 트래버스 중에 각 노드를 처리하는 더 실용적인 용도를 보여 줍니다.

void FindRoot(Node node, Action<Node> processNode)
{
    for (var current = node; current != null; current = current.Parent)
    {
        processNode(current);
    }
}

이전 코드는 current 변수를 역참조하기 위한 경고를 생성하지 않습니다. 정적 분석에서 currentmaybe-null이면 이 변수를 역참조하지 않는 것으로 확인합니다. current.Parent에 액세스하기 전과 currentProcessNode 작업에 전달하기 전에 current 변수가 null인지 검사됩니다. 이전 예제에서는 지역 변수가 초기화 또는 할당되거나 null과 비교될 때 컴파일러가 해당 변수의 null-state를 확인하는 방법을 보여 줍니다.

null 상태 분석은 호출된 메서드로 추적되지 않습니다. 결과적으로 생성자가 호출하는 공통 도우미 메서드에서 초기화된 필드는 다음 템플릿을 사용하여 경고를 생성합니다.

nullable이 아닌 속성 'name'은 생성자를 종료할 때 null이 아닌 값을 포함해야 합니다.

이러한 경고는 생성자 연결 또는 도우미 메서드의 null 허용 특성 이라는 두 가지 방법 중 하나로 해결할 수 있습니다. 다음 코드에서는 각 예제를 보여 줍니다. 클래스는 Person 다른 모든 생성자에서 호출하는 공통 생성자를 사용합니다. 클래스에는 Student 특성으로 주석이 추가된 도우미 메서드가 System.Diagnostics.CodeAnalysis.MemberNotNullAttribute 있습니다.


using System.Diagnostics.CodeAnalysis;

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    public Person() : this("John", "Doe") { }
}

public class Student : Person
{
    public string Major { get; set; }

    public Student(string firstName, string lastName, string major)
        : base(firstName, lastName)
    {
        SetMajor(major);
    }

    public Student(string firstName, string lastName) :
        base(firstName, lastName)
    {
        SetMajor();
    }

    public Student()
    {
        SetMajor();
    }

    [MemberNotNull(nameof(Major))]
    private void SetMajor(string? major = default)
    {
        Major = major ?? "Undeclared";
    }
}

참고

C# 10에는 한정된 할당 및 null 상태 분석에 몇 가지 개선이 적용되었습니다. C# 10으로 업그레이드하면 가양성인 null 허용 경고가 줄어든 것을 알 수 있습니다. 한정된 할당 개선 기능 사양에서 개선 사항에 대해 자세히 알아보세요.

Nullable 상태 분석 및 컴파일러가 생성하는 경고는 를 역참 null조하여 프로그램 오류를 방지하는 데 도움이 됩니다. nullable 경고 해결에 관한 문서에서는 코드에 표시될 수 있는 경고를 수정하는 기술을 제공합니다.

API 시그니처의 특성

null 상태 분석에는 API의 의미 체계를 이해하기 위한 개발자의 힌트가 필요합니다. 일부 API는 null 검사를 제공하며 변수의 null-statemaybe-null에서 not-null로 변경합니다. 다른 API는 입력 인수의 null-state에 따라 not-null 또는 maybe-null인 식을 반환합니다. 메시지를 표시하는 다음 코드를 예로 들어 보겠습니다.

public void PrintMessage(string message)
{
    if (!string.IsNullOrWhiteSpace(message))
    {
        Console.WriteLine($"{DateTime.Now}: {message}");
    }
}

검사를 기반으로 개발자는 이 코드를 안전한 것으로 간주하며 코드가 경고를 생성해서는 안 됩니다. 컴파일러는 IsNullOrWhiteSpace가 null 검사를 제공하는지 알지 못합니다. IsNullOrWhiteSpacefalse를 반환하는 경우에만 messagenot-null임을 컴파일러에 알리는 특성을 적용합니다. 이전 예제에서 시그니처에는 message의 null 상태를 나타내는 NotNullWhen이 포함되어 있습니다.

public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string message);

특성은 멤버를 호출하는 데 사용되는 개체 인스턴스의 인수, 반환 값, 멤버의 null 상태에 대해 자세한 정보를 제공합니다. 각 특성에 대한 자세한 내용은 null 허용 참조 특성에 대한 언어 참조 문서에서 찾을 수 있습니다. .NET 5에서 .NET 런타임 API에는 모두 주석이 달려 있습니다. 인수 및 반환 값의 null-state에 대한 의미 체계 정보를 제공하도록 고유 API에 주석을 달아 정적 분석을 개선합니다.

null 허용 변수 주석

null-state 분석은 대부분의 변수에 대해 강력한 분석을 제공합니다. 멤버 변수에 대한 더 자세한 정보를 컴파일러에 제공해야 합니다. 컴파일러는 퍼블릭 멤버에 액세스하는 순서를 가정할 수 없습니다. 모든 퍼블릭 멤버에 원하는 순서대로 액세스할 수 있습니다. 액세스 가능한 생성자는 개체를 초기화하는 데 사용할 수 있습니다. 멤버 필드를 null로 설정할 수 있는 경우 컴파일러는 각 메서드의 시작 부분에서 null-statemaybe-null이라고 가정해야 합니다.

변수가 null 허용 참조 형식 또는 null을 허용하지 않는 참조 형식인지 선언할 수 있는 주석을 사용합니다. 이러한 주석은 변수의 null-state에 대한 중요한 문을 생성합니다.

  • 참조는 null이 아니어야 합니다. null을 허용하지 않는 참조 변수의 기본 상태는 not-null입니다. 컴파일러는 null이 아닌지 먼저 확인하지 않고 이러한 참조를 역참조하기에 안전한지 확인하는 규칙을 적용합니다.
    • 이 변수는 null이 아닌 값으로 초기화되어야 합니다.
    • 이 변수에는 null 값을 절대로 할당할 수 없습니다. 코드가 null이면 안 되는 변수에 maybe-null 식을 할당하면 컴파일러가 경고를 발생시킵니다.
  • 참조에 null이 허용됩니다. null 허용 참조 변수의 기본 상태는 maybe-null입니다. 컴파일러는 null 참조를 올바르게 검사했는지 확인하는 규칙을 적용합니다.
    • 컴파일러가 해당 값이 null이 아님을 보장할 수 있는 경우에만 변수를 역참조할 수 있습니다.
    • 이러한 변수는 기본 null 값으로 초기화할 수 있으며 다른 코드에서 null 값을 할당할 수 있습니다.
    • 코드가 null일 수도 있는 변수에 maybe-null 식을 할당하면 컴파일러가 경고를 발생시키지 않습니다.

null이 아니어야 하는 참조 변수는 not-nullnull-state를 가집니다. 처음에 null일 수도 있는 참조 변수는 maybe-nullnull-state를 가집니다.

nullable 참조 형식nullable 값 형식과 동일한 구문을 사용하여 작성합니다. 변수 형식에 ?가 추가됩니다. 예를 들어 다음 변수 선언은 nullable 문자열 변수 name을 나타냅니다.

string? name;

형식 이름에 ?가 추가되지 않은 모든 변수는 null을 허용하지 않는 참조 형식입니다. 여기에는 이 기능을 설정한 기존 코드에 있는 모든 참조 형식 변수가 포함됩니다. 그러나 암시적 형식 지역 변수(var을 사용하여 선언됨)는 null 허용 참조 형식입니다. 앞의 섹션에서 설명한 것처럼 정적 분석은 지역 변수의 null-state를 확인하여 maybe-null인지 여부를 판단합니다.

경우에 따라 변수가 null이 아님을 알고 있지만 컴파일러에서는 변수의 null-statemaybe-null임을 판단하는 경우 경고를 재정의해야 합니다. null-forgiving 연산!자를 변수 이름 다음에 사용하여 null 상태를 null아님으로 강제 적용합니다. 예를 들어 name 변수가 null이 아닌 것으로 알고 있는데 컴파일러 경고가 발생하는 경우 다음 코드를 작성하여 컴파일러 분석을 재정의할 수 있습니다.

name!.Length;

null 허용 참조 형식 및 null 허용 값 형식은 유사한 의미 체계 개념을 제공합니다. 즉, 변수는 값이나 개체를 나타낼 수 있거나 해당 변수가 null일 수 있습니다. 그러나 null 허용 참조 형식과 null 허용 값 형식은 서로 다르게 구현됩니다. null 허용 값 형식은 System.Nullable<T>을 사용하여 구현되고, null 허용 참조 형식은 컴파일러에서 읽는 특성에 의해 구현됩니다. 예를 들어 string?string은 둘 다 동일한 형식(System.String)으로 표현됩니다. 그러나 int?int는 각각 System.Nullable<System.Int32>System.Int32로 표현됩니다.

Nullable 참조 형식은 컴파일 시간 기능입니다. 즉, 호출자는 경고를 무시하고 의도적으로 nullable이 아닌 참조가 필요한 메서드에 대한 인수로 사용할 null 수 있습니다. 라이브러리 작성자는 null 인수 값에 대한 런타임 검사를 포함해야 합니다. 는 ArgumentNullException.ThrowIfNull 런타임에 null에 대해 매개 변수를 확인하는 데 선호되는 옵션입니다.

중요

nullable 주석을 사용하도록 설정하면 Entity Framework Core에서 데이터 멤버가 필요한지 확인하는 방법이 변경될 수 있습니다. Entity Framework 핵심 기본 사항: Nullable 참조 형식 작업 문서에서 자세한 내용을 알아볼 수 있습니다.

제네릭

제네릭에는 임의 형식 매개 변수 T에 대한 T?를 처리하는 자세한 규칙이 필요합니다. null 허용 값 형식과 null 허용 참조 형식의 기록과 서로 다른 구현으로 인해 규칙은 자세히 설명되어야 합니다. Null 허용 값 형식System.Nullable<T> 구조체를 사용하여 구현됩니다. Null 허용 참조 형식은 컴파일러에 의미 체계 규칙을 제공하는 형식 주석으로 구현됩니다.

  • T의 형식 인수가 참조 형식인 경우 T?는 해당 null 허용 참조 형식을 참조합니다. 예를 들어, Tstring이면 T?string?입니다.
  • T의 형식 인수가 값 형식이면 T?는 동일한 값 형식 T를 참조합니다. 예를 들어, Tint이면 T?int입니다.
  • T의 형식 인수가 null 허용 참조 형식인 경우 T?는 동일한 null 허용 참조 형식을 참조합니다. 예를 들어, Tstring?이면 T?string?입니다.
  • T의 형식 인수가 null 허용 값 형식인 경우 T?는 동일한 null 허용 값 형식을 참조합니다. 예를 들어, Tint?이면 T?int?입니다.

반환 값의 경우 T?[MaybeNull]T에 해당하고, 인수 값의 경우 T?[AllowNull]T에 해당합니다. 자세한 내용은 언어 참조의 null-state 분석을 위한 특성 문서를 참조하세요.

제약 조건을 사용하여 다른 동작을 지정할 수 있습니다.

  • class 제약 조건은 T가 null을 허용하지 않는 참조 형식(예: string)이어야 함을 의미합니다. T에 대해 string?와 같은 null 허용 참조 형식을 사용하는 경우 컴파일러가 경고를 생성합니다.
  • class? 제약 조건은 T가 null을 허용하지 않는 참조 형식(string) 또는 null 허용 참조 형식(예: string?)이어야 함을 의미합니다. 형식 매개 변수가 string?와 같은 null 허용 참조 형식인 경우 T?의 식은 string?와 같은 동일한 null 허용 참조 형식을 참조합니다.
  • notnull 제약 조건은 T가 null을 허용하지 않는 참조 형식 또는 null을 허용하지 않는 값 형식이어야 함을 의미합니다. 형식 매개 변수에 null 허용 참조 형식 또는 null 허용 값 형식을 사용하는 경우 컴파일러가 경고를 생성합니다. 또한 T가 값 형식인 경우 반환 값은 해당 null 허용 값 형식이 아닌 이 값 형식입니다.

이러한 제약 조건은 T가 사용되는 방식에 대한 자세한 정보를 컴파일러에 제공하는 데 도움이 됩니다. 이는 개발자가 T의 형식을 선택할 때 도움이 되며 제네릭 형식의 인스턴스를 사용할 때 더 나은 null-state 분석을 제공합니다.

Nullable 컨텍스트

System.NullReferenceException을 throw하는 것을 방지하는 새 기능은 기존 코드베이스에서 사용할 때 중단을 유발할 수 있습니다.

  • 명시적 형식의 참조 변수는 모두 null을 허용하지 않는 참조 형식으로 해석됩니다.
  • 제네릭의 class 제약 조건의 의미가 null을 허용하지 않는 참조 형식을 의미하도록 변경되었습니다.
  • 이러한 새 규칙으로 인해 새로운 경고가 생성됩니다.

기존 프로젝트에서 이러한 기능을 사용하도록 명시적으로 옵트인해야 합니다. 그러면 마이그레이션 경로가 제공되고 이전 버전과의 호환성이 유지됩니다. Nullable 컨텍스트를 통해 컴파일러가 참조 형식 변수를 해석하는 방식을 미세하게 제어할 수 있습니다. null 허용 주석 컨텍스트가 컴파일러의 동작을 결정합니다. null 허용 주석 컨텍스트에는 4개의 값이 있습니다.

  • disable: 코드는 nullable을 알지 못합니다.
    • null 허용 경고가 사용되지 않습니다.
    • 모든 참조 형식 변수는 null 허용 참조 형식입니다.
    • 형식에서 ? 접미사를 사용하여 변수를 null 허용 참조 형식으로 선언할 수 없습니다.
    • null forgiving 연산자인 !를 사용할 수 있지만 영향은 없습니다.
  • enable: 컴파일러는 모든 null 참조 분석 및 모든 언어 기능을 사용하도록 설정합니다.
    • 모든 새 null 허용 경고가 사용됩니다.
    • ? 접미사를 사용하여 null 허용 참조 형식을 선언할 수 있습니다.
    • 다른 모든 참조 형식 변수는 null을 허용하지 않는 참조 형식입니다.
    • null forgiving 연산자는 null에 대한 가능한 할당을 알리는 경고를 표시하지 않습니다.
  • warnings: 컴파일러가 모든 null 분석을 수행하고 코드가 null을 역참조할 수 있는 경우 경고를 내보냅니다.
    • 모든 새 null 허용 경고가 사용됩니다.
    • ? 접미사를 사용하여 null 허용 참조 형식을 선언하면 경고가 생성됩니다.
    • 모든 참조 형식 변수는 null일 수 있습니다. 그러나 멤버는 ? 접미사로 선언되지 않은 경우 모든 메서드의 여는 괄호에 not-nullnull-state를 가집니다.
    • null forgiving 연산자인 !를 사용할 수 있습니다.
  • annotations: 컴파일러가 null 분석을 수행하지 않거나 코드가 null을 역참조할 수 있을 때 경고를 내보냅니다.
    • 새로운 null 허용 경고가 모두 사용 안 함으로 설정됩니다.
    • ? 접미사를 사용하여 null 허용 참조 형식을 선언할 수 있습니다.
    • 다른 모든 참조 형식 변수는 null을 허용하지 않는 참조 형식입니다.
    • null forgiving 연산자인 !를 사용할 수 있지만 영향은 없습니다.

.csproj 파일에 <Nullable> 요소를 사용하여 프로젝트에 대한 nullable 주석 컨텍스트 및 nullable 경고 컨텍스트를 설정할 수 있습니다. 이 요소는 컴파일러가 형식의 null 허용 여부를 해석하는 방법 및 내보내는 경고를 구성합니다. 다음 표에서는 허용 가능한 값을 보여주고 지정한 컨텍스트를 요약합니다.

컨텍스트 Dereference 경고 할당 경고 참조 형식 ? 접미사 ! 연산자
disable 사용 안 함 사용 안 함 모두 null 허용입니다. 사용할 수 없습니다. 아무런 영향이 없습니다.
enable 사용 사용 ?로 선언하지 않는 한 null을 허용하지 않음 nullable 형식 선언 가능한 null 할당에 대한 경고를 표시하지 않습니다.
warnings 사용 해당 없음 모두 null 허용이지만 메서드의 여는 중괄호에서 멤버는 null이 아닌 것으로 간주됩니다. 경고 생성 가능한 null 할당에 대한 경고를 표시하지 않습니다.
annotations 사용 안 함 사용 안 함 ?로 선언하지 않는 한 null을 허용하지 않음 nullable 형식 선언 아무런 영향이 없습니다.

사용하지 않도록 설정된 컨텍스트에서 컴파일된 코드의 참조 형식 변수는 nullable-oblivious입니다. null 리터럴이나 maybe-null 변수를 nullable oblivious인 변수에 할당할 수 있습니다. 그러나 nullable-oblivious 변수의 기본 상태는 not-null입니다.

프로젝트에 가장 적합한 설정을 선택할 수 있습니다.

  • 진단 또는 새 기능에 따라 업데이트하지 않으려는 레거시 프로젝트에 대해 사용 안 함을 선택합니다.
  • 코드가 System.NullReferenceException을 throw할 수 있는 경우 warnings를 선택합니다. null을 허용하지 않는 참조 형식을 사용하도록 코드를 수정하기 전에 이러한 경고를 해결할 수 있습니다.
  • 경고를 사용하기 전에 설계 의도를 표현하려면 annotations를 선택합니다.
  • null 참조 예외로부터 보호하려는 새 프로젝트 및 활성 프로젝트에 대해 사용을 선택합니다.

예제:

<Nullable>enable</Nullable>

또한 지시문을 사용하여 소스 코드의 아무 곳에나 이러한 동일한 컨텍스트를 설정할 수도 있습니다. 이러한 지시문은 대규모 코드베이스를 마이그레이션할 때 가장 유용합니다.

  • #nullable enable: 사용하도록 설정할 nullable 주석 컨텍스트 및 null 허용 경고 컨텍스트를 설정합니다.
  • #nullable disable: nullable 주석 컨텍스트 및 nullable 경고 컨텍스트를 사용하지 않도록 설정합니다.
  • #nullable restore: nullable 주석 컨텍스트와 nullable 경고 컨텍스트를 프로젝트 설정으로 복원합니다.
  • #nullable disable warnings: nullable 경고 컨텍스트를 사용하지 않도록 설정합니다.
  • #nullable enable warnings: 사용하도록 nullable 경고 컨텍스트를 설정합니다.
  • #nullable restore warnings: nullable 경고 컨텍스트를 프로젝트 설정으로 복원합니다.
  • #nullable disable annotations: nullable 주석 컨텍스트를 사용하지 않도록 설정합니다.
  • #nullable enable annotations: 사용하도록 nullable 주석 컨텍스트를 설정합니다.
  • #nullable restore annotations: 주석 경고 컨텍스트를 프로젝트 설정으로 복원합니다.

모든 코드 줄에 대해 다음 조합 중 원하는 것을 설정할 수 있습니다.

경고 컨텍스트 주석 컨텍스트 사용
프로젝트 기본값 프로젝트 기본값 기본값
enable disable 분석 경고 수정
enable 프로젝트 기본값 분석 경고 수정
프로젝트 기본값 enable 형식 주석 추가
enable enable 이미 마이그레이션된 코드
disable enable 경고를 수정하기 전에 코드에 주석 달기
disable disable 마이그레이션된 프로젝트에 레거시 코드 추가
프로젝트 기본값 disable 거의 없음
disable 프로젝트 기본값 거의 없음

이러한 9가지 조합은 컴파일러가 코드에 대해 내보내는 진단에 대한 세분화된 제어를 제공합니다. 아직 해결할 준비가 되지 않은 추가 경고가 표시되지 않고 업데이트하는 모든 영역에서 더 많은 기능을 사용하도록 설정할 수 있습니다.

중요

전역 null 허용 컨텍스트는 생성된 코드 파일에 적용되지 않습니다. 두 전략에서 null 허용 컨텍스트는 생성됨으로 표시된 모든 소스 파일에 대해 disabled입니다. 즉, 생성된 파일의 API가 주석 처리되지 않습니다. 다음 네 가지 방법으로 파일은 생성됨으로 표시됩니다.

  1. .editorconfig에서 해당 파일에 적용되는 섹션에 generated_code = true를 지정합니다.
  2. 파일의 맨 위에 있는 주석에 <auto-generated> 또는 <auto-generated/>를 배치합니다. 해당 주석의 모든 줄에 넣을 수 있지만 주석 블록은 파일의 첫 번째 요소여야 합니다.
  3. 파일 이름을 TemporaryGeneratedFile_ 로 시작합니다.
  4. 파일 이름을 .designer.cs, .generated.cs, .g.cs 또는 .g.i.cs로 종료합니다.

생성기는 #nullable 전처리기 지시문을 사용하여 옵트인할 수 있습니다.

기본 nullable 주석 및 경고 컨텍스트는 disabled입니다. 이는 기존 코드가 변경 없이 새로운 경고를 생성하지 않고 컴파일됨을 의미합니다. .NET 6부터 새 프로젝트에는 모든 프로젝트 템플릿에 <Nullable>enable</Nullable> 요소가 포함됩니다.

이러한 옵션은 null 허용 참조 형식을 사용하도록 기존 코드베이스를 업데이트하는 두 가지 고유한 전략을 제공합니다.

알려진 문제

참조 형식을 포함하는 배열 및 구조체는 null 허용 참조뿐만 아니라 null 안전을 확인하는 정적 분석에서도 알려진 함정입니다. 두 경우 모두 null을 허용하지 않는 참조 형식이 경고를 생성하지 않고 null로 초기화될 수 있습니다.

구조체

null을 허용하지 않는 참조 형식을 포함하는 구조에서는 경고 없이 default를 할당할 수 있습니다. 다음 예제를 참조하세요.

using System;

#nullable enable

public struct Student
{
    public string FirstName;
    public string? MiddleName;
    public string LastName;
}

public static class Program
{
    public static void PrintStudent(Student student)
    {
        Console.WriteLine($"First name: {student.FirstName.ToUpper()}");
        Console.WriteLine($"Middle name: {student.MiddleName?.ToUpper()}");
        Console.WriteLine($"Last name: {student.LastName.ToUpper()}");
    }

    public static void Main() => PrintStudent(default);
}

앞의 예제에서 null을 허용하지 않는 참조 형식 FirstNameLastName이 null인 동안 PrintStudent(default)에는 경고가 없습니다.

또 다른 일반적인 사례는 일반 구조체를 처리하는 경우입니다. 다음 예제를 참조하세요.

#nullable enable

public struct Foo<T>
{
    public T Bar { get; set; }
}

public static class Program
{
    public static void Main()
    {
        string s = default(Foo<string>).Bar;
    }
}

앞의 예제에서 Bar 속성은 런타임에 null이 되고 null을 허용하지 않는 문자열에 경고 없이 할당됩니다.

배열

배열은 nullable 참조 형식의 알려진 문제가 되기도 합니다. 경고를 생성하지 않는 다음 예제를 고려하세요.

using System;

#nullable enable

public static class Program
{
    public static void Main()
    {
        string[] values = new string[10];
        string s = values[0];
        Console.WriteLine(s.ToUpper());
    }
}

앞의 예제에서 배열 선언은 해당 요소가 모두 null로 초기화되는 동안 null을 허용하지 않는 문자열을 보유함을 나타냅니다. 그런 다음, s 변수에는 null 값(배열의 첫 번째 요소)이 할당됩니다. 마지막으로 s 변수가 역참조되어 런타임 예외가 발생합니다.

참조