Aşırı yüklenmiş operatöre eşittir
Aslında null
, ==
operatöre aşırı yüklenen bir türle karşılaştırdığınızda iki karşılaştırma arasında anlambilimde bir fark vardır . foo is null
sonucu belirlemek için doğrudan referans karşılaştırmasını kullanacak, oysa foo == null
aşırı yüklenmiş ==
operatörü elbette çalıştıracaktır .
Bu örnekte, aşırı yüklenmiş işleçte bir "hata" ==
ekledim ve ikinci argüman ise her zaman bir istisna atmasına neden oldu null
:
void Main()
{
Foo foo = null;
if (foo is null) Console.WriteLine("foo is null"); // This condition is met
if (foo == null) Console.WriteLine("foo == null"); // This will throw an exception
}
public class Foo
{
public static bool operator ==(Foo foo1, Foo foo2)
{
if (object.Equals(foo2, null)) throw new Exception("oops");
return object.Equals(foo1, foo2);
}
// ...
}
IL kodu, doğrudan referans karşılaştırması yapmak foo is null
için ceq
talimatı kullanır :
IL_0003: ldloc.0 // foo
IL_0004: ldnull
IL_0005: ceq
IL kodu foo == null
, aşırı yüklenmiş operatöre bir çağrı kullanır:
IL_0016: ldloc.0 // foo
IL_0017: ldnull
IL_0018: call UserQuery+Foo.op_Equality
Yani fark, eğer kullanırsanız, ==
kullanıcı kodunu çalıştırma riskiniz olabilir (bu, beklenmedik davranış veya performans sorunları yaşayabilir).
Jenerikler üzerinde kısıtlama
is null
Yapı kullanmak, türü bir başvuru türüyle sınırlar. Derleyici bunu sağlar, yani is null
bir değer türünde kullanamazsınız . Genel bir yönteminiz varsa is null
, genel tür bir başvuru türü olarak kısıtlanmadığı sürece kullanamazsınız .
bool IsNull<T>(T item) => item is null; // Compile error: CS0403
bool IsNull<T>(T item) => item == null; // Works
bool IsNull<T>(T item) where T : class => item is null; // Works
Bunu işaret ettiği için David Augusto Villa'ya teşekkürler .