कोडिंग अभ्यास C# में समानता के कई गुण दिखाता है:
Object.Equals()== और != से की जाती है। इन टाइप के साथ उपलब्ध Equals() मेथड इस्तेमाल करने की तुलना में इसे ज़्यादा स्वाभाविक माना जाता है। Java प्रोग्रामर को स्ट्रिंग के साथ काम करते समय इस बात का ध्यान रखना चाहिए कि == C# में वैल्यू की तुलना करता है, जबकि अपनी पुरानी भाषा Java में लौटने पर वह रेफ़रेंस की तुलना करता है।object से विरासत में मिले Equals() मेथड से की जाती है। अगर समानता की जाँच का आपका उद्देश्य यह पक्का करना है कि दो ऑब्जेक्ट बिलकुल एक ही इंस्टेंस हैं, तो object के इम्प्लीमेंटेशन पर भरोसा करना काफ़ी है। अगर नहीं, तो आपको object.Equals() को ओवरराइड करना होगा।Equals() को ओवरराइड करना ज़रूरी है।Equals() साधारण टाइप के मेंबर की समानता की जाँच == से करता है और रेफ़रेंस टाइप की जाँच Equals() में रिकर्सिव कॉल से।class StatusBar
{
private readonly int width = 200, height = 20;
public override bool Equals(object other)
{
// ... null and type checks and performance optimisations
return width == (other as StatusBar).width && height == (other as StatusBar).height;
}
}
class Window
{
private readonly string title = "Main";
private readonly StatusBar statusBar = new StatusBar();
public override bool Equals(object other)
{
// ... null and type checks and performance optimisations
return title == (other as Window).title && statusBar.Equals((other as Window).statusBar);
}
}
object.ReferenceEquals() का उपयोग दो ऑब्जेक्ट की तुलना करके यह पता लगाने के लिए किया जाता है कि वे एक ही इंस्टेंस हैं या नहीं। इससे स्पष्टता आती है, और जहाँ Equals() तथा == को ओवरराइड या ओवरलोड किया गया हो वहाँ यह ज़रूरी भी हो जाता है।var winA = new Window(); // above code shows that all windows are equal
var winB = new Window();
ReferenceEquals(winA, winB);
// => false
var winC = winA;
ReferenceEquals(winA, winC);
// => true
public override bool Equals(object obj) के अलावा, IDE अक्सर protected bool Equals(FacialFeatures other) ओवरलोड भी बना देते हैं, जो इनहेरिटेंस के समय काम आता है। व्युत्पन्न क्लास बेस क्लास के Equals() को कॉल कर सकती है और फिर अपनी जाँच जोड़ सकती है।== का इस्तेमाल तब तक न कीजिए जब तक कि आपने अपनी क्लास में == ऑपरेटर और Equals() मेथड को ओवरलोड न कर लिया हो (देखिए operator-overloading अभ्यास), या जब तक आपके लिए सिर्फ़ रेफ़रेंस का बराबर होना ही मायने न रखता हो।structs में समानता की जाँच structs अभ्यास में की गई है।tuples की समानता tuples अभ्यास में की गई है।protected bool Equals(T other)
{
return field1 == other.field1 && field2.Equals(other.field2);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((T) obj);
}
SequenceEquals() देता है, लेकिन LINQ के बिना दोनों कलेक्शन पर इटरेशन करके हर आइटम की अलग-अलग तुलना करनी पड़ती है।== और != कैसे इस्तेमाल करें, इसकी चर्चा operator-overloading अभ्यास में देखिए।Object.GetHashCode()object.GetHashCode() 32 बिट के पूर्णांक के रूप में हैश कोड लौटाता है। डिक्शनरी और सेट क्लास, जैसे Dictionary<T> और HashSet<T>, इस हैश कोड का उपयोग ऑब्जेक्ट को तेज़ी से संग्रहीत करने और निकालने के लिए करती हैं। डिक्शनरी के मामले में हैशिंग का संबंध की (key) से होता है।Equals() को ओवरराइड करते हैं तो GetHashCode() को भी ओवरराइड करेंगे। Equals() और GetHashCode() के बीच एक ऐसा संबंध है जो डिक्शनरी और हैश सेट क्लास तथा हैश कोड इस्तेमाल करने वाली अन्य क्लास के सही व्यवहार के लिए सही होना ज़रूरी है। आपसे अपेक्षा है कि आप यह मेथड इस तरह लागू करें कि भविष्य में हैश कोड पर आधारित कलेक्शन जोड़ने वाले मेंटेनर के लिए कोई जाल न बिछे।Equal() सही लौटाता है) तो दोनों ऑब्जेक्ट का GetHashCode() एक ही वैल्यू लौटाना चाहिए। उलटी दिशा में यह लागू नहीं होता। यह संबंध दोनों तरफ़ से नहीं है। सोचिए एक लुकअप फंक्शन की, जो पहले हैश कोड के आधार पर किसी "बकेट" में जाता है और फिर समानता की जाँच से वह खास आइटम चुन लेता है।HashCode.Combine() को कॉल करना और उसमें वे वैल्यू पास करना जो समानता की जाँच में इस्तेमाल होती हैं (या उनका कोई हिस्सा)। ध्यान रखिए कि Combine() को आप जितनी ज़्यादा जानकारी देंगे, हैश का इम्प्लीमेंटेशन उतना ही तेज़ होने की संभावना है।public class Assessment
{
private int rating;
private Person boss;
public override int GetHashCode()
{
return HashCode.Combine(rating, boss);
}
}
परफ़ॉर्मेंस को थोड़ा बेहतर बनाने के लिए, खास तौर पर जब ऑब्जेक्ट किसी कलेक्शन का हिस्सा हों, आप एक ओवरलोडेड मेंबर public bool Equals(T other) जोड़ सकते हैं।
इससे रेफ़रेंस टाइप के लिए कुछ टाइप जाँच बच जाती है और वैल्यू टाइप के लिए बॉक्सिंग का एक चरण बच जाता है, क्योंकि उन्हें public override bool Equals(object other) के आर्गुमेंट के रूप में ऑब्जेक्ट में बदलने (बॉक्स करने) की ज़रूरत नहीं पड़ती।
अगर आप अपनी क्लास में IEquatable<T> इंटरफ़ेस जोड़ते हैं तो यह ओवरलोड लागू करना ज़रूरी हो जाता है। जब तक आपके कोड में ऐसे रूटीन न हों जो IEquatable<T> टाइप के ऑब्जेक्ट लेते हों (और इम्प्लीमेंट करने वाली क्लास से परे, शायद समानता से जुड़ा कुछ दिलचस्प काम करते हों), इंटरफ़ेस शामिल करने की और कोई खास वजह नहीं है।
IEqualityComparer<T>अगर आपकी कोई क्लास दो अलग-अलग तरीकों से विशिष्ट रूप से पहचानी जा सकती है, जैसे Person क्लास जिसका एक SSID और एक अलग ईमेल पता है, तो .NET ऐसा तरीका देता है जिससे दो अलग-अलग कलेक्शन अलग-अलग हैश कोड और समानता की जाँच इस्तेमाल कर सकते हैं। हर कलेक्शन के पास IEqualityComparer<T> का अपना अलग इम्प्लीमेंटेशन हो सकता है, जिसमें अपना Equals() और GetHashCode() मेथड हो। आपके पास एक डिक्शनरी हो सकती है जो SSID पर आधारित हो और दूसरी जो ईमेल पते पर।
जहाँ IEqualityComparer<T> इस्तेमाल हो रहा हो, वहाँ भी आम तौर पर आप अपनी आइटम क्लास पर Equals() और GetHashCode() को ओवरराइड करेंगे, ताकि कलेक्शन क्लास के बाहर दिक्कतें न हों।
IEqualityComparer<T> इस्तेमाल करते समय एक बात ध्यान में रखनी होती है: प्राइवेट मेथड आदि समानता की जाँच के लिए उपलब्ध नहीं रहेंगे।
अगर सिर्फ़ एक ही हैश वाला कलेक्शन इस्तेमाल में है, तो बेहतर होगा कि IEqualityComparer<T> से बचें और समानता तथा हैश कोड को ऑब्जेक्ट के अंदर ही समेट लें। सबसे पहले तो यह आदर्श नहीं है कि ऑब्जेक्ट और हैश वाले कलेक्शन के बीच की ज़रूरी निर्भरता को कंपाइलर लागू नहीं करा सकता, लेकिन अगर हैशिंग और तुलना का तर्क कहीं और हो, तो मेंटेनर के लिए क्लास के मेंबर बदलना और भी आसान हो जाएगा, चाहे उसका कलेक्शन पर क्या असर पड़ेगा, इसका ध्यान न रहे।
एक प्रिमिटिव जो लापरवाह कोडर के लिए चुनौती बन सकता है, वह है फ़्लोटिंग-पॉइंट वैल्यू की समानता की जाँच। इस पर floating-point-numbers कॉन्सेप्ट के about.md दस्तावेज़ में चर्चा की गई है।
यह लेख उन कुछ फैसलों को दिखाता है जो समानता और इनहेरिटेंस के संबंध में लेने पड़ते हैं। ये आपके लिए तभी मायने रखेंगे जब आप किसी क्लास और उससे व्युत्पन्न क्लास के इंस्टेंस पर काम कर रहे हों और दोनों के बीच समानता जाँचनी हो।