다음을 통해 공유


제약이 없는 형식 매개 변수 주석

메모

이 문서는 기능 사양입니다. 사양은 기능의 디자인 문서 역할을 합니다. 여기에는 기능 디자인 및 개발 중에 필요한 정보와 함께 제안된 사양 변경 내용이 포함됩니다. 이러한 문서는 제안된 사양 변경이 완료되고 현재 ECMA 사양에 통합될 때까지 게시됩니다.

기능 사양과 완료된 구현 간에 약간의 불일치가 있을 수 있습니다. 이러한 차이는 관련된LDM(언어 디자인 모임) 노트에 기록됩니다.

사양문서에서 C# 언어 표준에 기능 사양을 채택하는 과정에 대해 더 자세히 알아볼 수 있습니다.

챔피언 이슈: https://github.com/dotnet/csharplang/issues/3297

요약

값 형식 또는 참조 형식으로 제한되지 않는 형식 매개 변수에 대해 nullable 주석을 허용합니다. T?.

static T? FirstOrDefault<T>(this IEnumerable<T> collection) { ... }

? 주석

C#8에서 ? 주석은 값 형식 또는 참조 형식으로 명시적으로 제한된 형식 매개 변수에만 적용할 수 있습니다. C#9에서는 제약 조건에 관계없이 모든 형식 매개 변수에 ? 주석을 적용할 수 있습니다.

형식 매개 변수가 명시적으로 값 형식으로 제한되지 않는 한 주석은 #nullable enable 컨텍스트 내에서만 적용할 수 있습니다.

형식 매개 변수 T 참조 형식으로 대체되는 경우 T? 해당 참조 형식의 nullable 인스턴스를 나타냅니다.

var s1 = new string[0].FirstOrDefault();  // string? s1
var s2 = new string?[0].FirstOrDefault(); // string? s2

T 값 형식으로 대체되는 경우 T?T인스턴스를 나타냅니다.

var i1 = new int[0].FirstOrDefault();  // int i1
var i2 = new int?[0].FirstOrDefault(); // int? i2

T 주석이 추가된 형식 U?대체되는 경우 T?U??대신 주석이 추가된 형식 U? 나타냅니다.

var u1 = new U[0].FirstOrDefault();  // U? u1
var u2 = new U?[0].FirstOrDefault(); // U? u2

T이(가) U의 유형으로 대체되면, T?#nullable disable 컨텍스트 내에서도 U?를 나타냅니다.

#nullable disable
var u3 = new U[0].FirstOrDefault();  // U? u3

반환 값의 경우 T?[MaybeNull]T; 인수 값의 경우 T?[AllowNull]T동일합니다. C#8로 컴파일된 어셈블리에서 인터페이스를 재정의하거나 구현하는 경우 동등성이 중요합니다.

public abstract class A
{
    [return: MaybeNull] public abstract T F1<T>();
    public abstract void F2<T>([AllowNull] T t);
}

public class B : A
{
    public override T? F1<T>() where T : default { ... }       // matches A.F1<T>()
    public override void F2<T>(T? t) where T : default { ... } // matches A.F2<T>()
}

default 제약 조건

기존 코드에서 재정의되거나 명시적으로 구현된 제네릭 메서드는 명시적 제약 조건 절을 포함할 수 없습니다. 따라서 값 형식인 T에 대해 재정의되거나 명시적으로 구현된 메서드 내에서 T?Nullable<T>으로 처리됩니다.

참조 형식으로 제한되는 형식 매개 변수에 대한 주석을 허용하기 위해 C#8에서는 재정의되거나 명시적으로 구현된 메서드에서 명시적 where T : classwhere T : struct 제약 조건을 허용했습니다.

class A1
{
    public virtual void F1<T>(T? t) where T : struct { }
    public virtual void F1<T>(T? t) where T : class { }
}

class B1 : A1
{
    public override void F1<T>(T? t) /*where T : struct*/ { }
    public override void F1<T>(T? t) where T : class { }
}

참조 형식 또는 값 형식으로 제한되지 않은 형식 매개 변수에 대한 주석을 허용하기 위해 C#9에서는 새 where T : default 제약 조건을 허용합니다.

class A2
{
    public virtual void F2<T>(T? t) where T : struct { }
    public virtual void F2<T>(T? t) { }
}

class B2 : A2
{
    public override void F2<T>(T? t) /*where T : struct*/ { }
    public override void F2<T>(T? t) where T : default { }
}

메서드 재정의 또는 명시적 구현 이외의 default 제약 조건을 사용하는 것은 오류입니다. 재정의되거나 인터페이스 메서드의 해당 형식 매개 변수가 참조 형식 또는 값 형식으로 제한될 때 default 제약 조건을 사용하는 것은 오류입니다.

디자인 회의