Bagikan melalui


Anotasi parameter tipe tanpa batasan

Nota

Artikel ini adalah spesifikasi fitur. Spesifikasi berfungsi sebagai dokumen desain untuk fitur tersebut. Ini termasuk perubahan spesifikasi yang diusulkan, bersama dengan informasi yang diperlukan selama desain dan pengembangan fitur. Artikel ini diterbitkan sampai perubahan spesifikasi yang diusulkan diselesaikan dan dimasukkan dalam spesifikasi ECMA saat ini.

Mungkin ada beberapa perbedaan antara spesifikasi fitur dan implementasi yang selesai. Perbedaan tersebut dicatat dalam catatan penting rapat desain bahasa (LDM) .

Anda dapat mempelajari lebih lanjut tentang proses untuk mengadopsi speklet fitur ke dalam standar bahasa C# dalam artikel tentang spesifikasi .

Edisi juara: https://github.com/dotnet/csharplang/issues/3297

Ringkasan

Izinkan anotasi nullable untuk parameter jenis yang tidak dibatasi oleh jenis nilai atau jenis referensi: T?.

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

anotasi ?

Di C#8, anotasi ? hanya dapat diterapkan ke parameter jenis yang secara eksplisit dibatasi untuk jenis nilai atau jenis referensi. Di C#9, anotasi ? dapat diterapkan ke parameter jenis apa pun, terlepas dari batasan.

Kecuali parameter jenis secara eksplisit dibatasi untuk jenis nilai, anotasi hanya dapat diterapkan dalam konteks #nullable enable.

Jika parameter jenis T diganti dengan jenis referensi, maka T? mewakili instans nullable dari jenis referensi tersebut.

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

Jika T diganti dengan jenis nilai, maka T? mewakili instans T.

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

Jika T diganti dengan jenis anotasi U?, maka T? mewakili jenis anotasi U? daripada U??.

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

Jika T diganti dengan jenis U, maka T? mewakili U?, bahkan dalam konteks #nullable disable.

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

Untuk nilai pengembalian, T? setara dengan [MaybeNull]T; untuk nilai argumen, T? setara dengan [AllowNull]T. Kesetaraan penting saat mengambil alih atau menerapkan antarmuka dari rakitan yang dikompilasi dengan 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>()
}

batasan default

Untuk kompatibilitas dengan kode yang ada, di mana metode generik yang ditimpa dan diimplementasikan secara eksplisit tidak dapat mencakup klausul batasan eksplisit, T? dalam metode yang ditimpa atau diimplementasikan secara eksplisit diperlakukan sebagai Nullable<T> di mana T adalah tipe nilai.

Untuk mengizinkan anotasi untuk parameter tipe yang dibatasi pada tipe referensi, C#8 mengizinkan kendala eksplisit where T : class dan where T : struct pada metode yang ditindih atau diimplementasi secara eksplisit.

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 { }
}

Untuk mengizinkan anotasi untuk parameter jenis yang tidak dibatasi untuk jenis referensi atau jenis nilai, C#9 memungkinkan batasan where T : default baru.

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 { }
}

Penggunaan pembatasan default selain pada penggantian metode atau implementasi eksplisit adalah suatu kesalahan. Ini adalah kesalahan untuk menggunakan batasan default ketika parameter jenis yang sesuai dalam metode yang ditimpa atau metode antarmuka dibatasi ke jenis referensi atau jenis nilai.

Rapat Desain