Halaman Galeri Resharper
Sejarah Perubahan
Gagasan dasar dari ekstensi ini adalah untuk mengubah perilaku analisis nullabilitas statis Resharper sehingga elemen kode spesifik mendapatkan anotasi nullability default tanpa menentukan atribut [NotNull] atau [CanBeNull] eksplisit. Misalnya, tipe referensi dalam parameter metode secara default [NotNull] (→ mereka membutuhkan [CanBeNull] eksplisit untuk menjadi tidak dapat dibatalkan).

Dengan diaktifkan nullabilitas implisit untuk elemen sintaks yang spesifik, dapat dikonfigurasi, aturan berikut berlaku.
[NotNull] .[CanBeNull] yang eksplisit.null secara implisit [CanBeNull] .Singkatnya, kode menunjukkan pada gambar di atas ...
public string Bar ( string a , [ CanBeNull ] string b , string c = null )
{
// ...
}... secara implisit menjadi ...
[ NotNull ]
public string Bar ( [ NotNull ] string a , [ CanBeNull ] string b , [ CanBeNull ] string c = null )
{
// ...
}[NotNull] sebagai default Tanpa ekstensi ini, nilai nullabilitas default "tidak diketahui" yang berarti bahwa Resharper tidak termasuk elemen -elemen ini untuk analisis nullabilitasnya. Sebagai hasil dari nullabilitas default yang diubah dari ekstensi ini kita harus menempatkan anotasi [CanBeNull] hanya untuk elemen kode tertentu (misalnya parameter tipe referensi di mana harus diizinkan untuk meneruskan null sebagai argumen) dan tidak memerlukan anotasi eksplisit untuk sebagian besar kasus (dalam basis kode yang mencoba mengurangi referensi null yang lewat ke minimum).
Resharper 9.2 memperkenalkan dukungan untuk analisis nullability untuk metode async ( Task<T> pengembalian). Dengan diaktifkan nullabilitas implisit untuk nilai pengembalian metode, Task<T> Metode pengembalian yang diketik juga menjadi secara implisit [ItemNotNull] (Resharper menggunakan atribut ini untuk merujuk pada nilai Task<T> ). Untuk Task<T> Nilai Pengembalian, ini dapat ditimpa dengan [ItemCanBeNull] .
Contoh program berikut berisi potensi NullReferenceException dalam command.Equals("Hello") karena programmer melewatkan bahwa GetCommand() juga dapat mengembalikan null .
public static void Main ( string [ ] args )
{
string command = GetCommand ( args ) ;
if ( command . Equals ( "Hello" ) )
Console . WriteLine ( "Hello World!" ) ;
}
private static string GetCommand ( string [ ] args )
{
if ( args . Length < 1 )
return null ;
return args [ 0 ] ;
}Dengan tidak dapat diaktifkan nullability bug ini akan terdeteksi dengan analisis statis Resharper.
null di GetCommand() karena metode ini akan secara implisit dijelaskan sebagai [NotNull] .[CanBeNull] ke GetCommand() .[CanBeNull] , Resharper sekarang akan memperingatkan tentang potensi NullReferenceException dalam command.Equals("Hello") panggilan di Main() . Dalam contoh di atas nullability implisit memaksa programmer untuk memperbaiki atribut [CanBeNull] yang hilang di GetCommand() . Ini menunjukkan bagaimana jumlah anotasi [CanBeNull] akan ditingkatkan dalam basis kode dan oleh karena itu tidak hanya meningkatkan analisis statis Resharper tetapi juga dokumentasi tanda tangan metode (kontrak).
Tujuan lain dari ekstensi ini adalah untuk membawa analisis statis Resharper dalam sinkronisasi dengan pemeriksaan nol implisit dari Fody Nullguard. Sebagai contoh, fody weaver ini menyuntikkan pernyataan throw new ArgumentNullException(/*...*/) untuk parameter metode ke dalam badan metode menggunakan aturan yang sama dengan nullability implisit . Dengan kata lain penenun ini menambahkan pemeriksaan runtime untuk nullability ke analisis statis Resharper.
C# 8 akan mendapatkan tipe referensi nullable yang membawa jenis opsi ke dalam bahasa C#. Ini cocok dengan semantik nullability implisit dan melangkah lebih jauh karena memperluasnya ke penduduk setempat, parameter generik, ... karena anotasi nullabilitas bekerja pada level tipe.
[ CanBeNull ]
string Bar ( [ CanBeNull ] string a , string b )
{
string result = a ;
return result ;
}... lalu sesuai dengan ...
string ? Bar ( string ? a , string b )
{
string ? result = a ;
return result ;
} Ini akan membuat nullability implisit tidak perlu di masa depan dan pada saat yang sama "jalur peningkatan" yang sempurna karena basis kode yang baik [CanBeNull] yang baik akan dengan mudah portabel ke C# 8.
Sejak versi 2016.1 mendukung resharper (dalam "mode internal") fitur yang sebanding (lihat Inspeksi Kode | Pengaturan ) dengan perbedaan berikut.
Nullability implisit ...
[NotNull] . Jenis elemen eksplisit atau implisit [NotNull] disorot dengan garis bawah bertitik. Bar [NotNull] [NotNull] [NotNull]
Sorotan dapat diaktifkan/dinonaktifkan pada halaman opsi nullability implisit , dan warna dapat dikonfigurasi dalam opsi "Fonts and Colors" Visual Studio.
Nullability implisit dapat diaktifkan atau dinonaktifkan untuk elemen sintaks tertentu dalam inspeksi kode | Halaman opsi nullabilitas implisit .

Nullability implisit juga dapat dikonfigurasi dengan kode menggunakan AssemblyMetadataAttribute . Ini memiliki keuntungan bahwa konfigurasi dikompilasi ke dalam perakitan sehingga konsumen perakitan dengan nullabilitas implisit terpasang mendapatkan anotasi nullabilitas implisit yang sama dari elemen kode yang dikompilasi seperti dalam solusi perpustakaan.
Contoh:
[ assembly : AssemblyMetadata ( "ImplicitNullability.AppliesTo" ,
"InputParameters, RefParameters, OutParametersAndResult, Fields, Properties" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.Fields" , "RestrictToReadonly" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.Properties" , "RestrictToGetterOnly" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.GeneratedCode" , "Exclude" ) ]Selain perubahan perilaku analisis nullabilitas, peringatan inspeksi kode berikut disediakan oleh ekstensi ini.
Untuk informasi lebih lanjut tentang peringatan ini (dan motivasi mereka) lihat deskripsi mereka dalam Inspeksi Kode Resharper | Halaman opsi keparahan inspeksi .
ID: ImplicitNotNullConflictInHierarchy
abstract class Base
{
public abstract void Method ( [ CanBeNull ] string a ) ;
}
class Derived : Base
{
// "Implicit NotNull conflicts with nullability in base type":
public override void Method ( string a )
{
}
} ID: ImplicitNotNullElementCannotOverrideCanBeNull
abstract class Base
{
[ CanBeNull ]
public abstract string Method ( ) ;
}
class Derived : Base
{
// "Implicit NotNull element cannot override CanBeNull in base type, nullability should be explicit":
public override string Method ( ) => "" ;
} IDS: ImplicitNotNullOverridesUnknownBaseMemberNullability resp. ImplicitNotNullResultOverridesUnknownBaseMemberNullability
class Derived : External . Class /* (external code with unannotated 'Method' and 'Function') */
{
// "Implicit NotNull overrides unknown nullability of base member, nullability should be explicit":
public override void Method ( string a )
{
}
// "Implicit NotNull result or out parameter overrides unknown nullability of base member,
// nullability should be explicit":
public override string Function ( ) => "" ;
} ID: NotNullOnImplicitCanBeNull
// "Implicit CanBeNull element has an explicit NotNull annotation":
void Foo ( [ NotNull ] int ? a )
{
} Terima kasih banyak kepada Fabian Schmied karena telah mendukung desain dan konsepsi nullabilitas implisit .