ओवरलोडेड बराबर ऑपरेटर
वास्तव में दोनों तुलनाओं के बीच शब्दार्थ में अंतर होता है जब आप nullएक प्रकार के साथ तुलना कर रहे हैं जिसने ==ऑपरेटर को अधिभारित किया है। foo is nullपरिणाम का निर्धारण करने के लिए प्रत्यक्ष संदर्भ तुलना का उपयोग करेगा, जबकि अगर यह मौजूद है तो foo == nullनिश्चित रूप से अतिभारित ==ऑपरेटर को चलाएगा ।
इस उदाहरण में मैंने ओवरलोडेड ==ऑपरेटर में एक "बग" पेश किया है , जिससे दूसरा तर्क होने पर इसे हमेशा एक अपवाद के रूप में फेंकना पड़ता है 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);
}
// ...
}
प्रत्यक्ष संदर्भ तुलना करने के लिए अनुदेश foo is nullका उपयोग करने के लिए IL कोड ceq:
IL_0003: ldloc.0 // foo
IL_0004: ldnull
IL_0005: ceq
foo == nullओवरलोड ऑपरेटर को कॉल करने के लिए IL कोड :
IL_0016: ldloc.0 // foo
IL_0017: ldnull
IL_0018: call UserQuery+Foo.op_Equality
तो अंतर यह है, कि यदि आप ==उपयोगकर्ता कोड चलाने में जोखिम का उपयोग करते हैं (जो संभवतः अप्रत्याशित व्यवहार या प्रदर्शन की समस्या हो सकती है)।
जेनेरिक पर प्रतिबंध
is nullकंस्ट्रक्शन के उपयोग से टाइप को रेफरेंस टाइप तक सीमित कर दिया जाता है। संकलक यह सुनिश्चित करता है, जिसका अर्थ है कि आप is nullमूल्य प्रकार पर उपयोग नहीं कर सकते हैं । यदि आपके पास एक सामान्य विधि है, तो आप is nullतब तक उपयोग नहीं कर पाएंगे जब तक कि सामान्य प्रकार एक संदर्भ प्रकार होने के लिए विवश न हो।
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
इस ओर इशारा करने के लिए डेविड ऑगस्टो विला का धन्यवाद ।