C# Language
बराबरी और GetHashCode
खोज…
टिप्पणियों
Equals
प्रत्येक कार्यान्वयन को निम्नलिखित आवश्यकताओं को पूरा करना चाहिए:
Reflexive : एक वस्तु को स्वयं के बराबर होना चाहिए।
x.Equals(x)
true
लौटाताtrue
।सममित : अगर मैं x की y या y से x से तुलना करता हूं तो कोई अंतर नहीं है - परिणाम समान है।
x.Equals(y)
y.Equals(x)
के समान मान लौटाता है।सकर्मक : यदि एक वस्तु किसी अन्य वस्तु के बराबर है और यह एक तीसरे के बराबर है, तो पहली को तीसरे के बराबर होना चाहिए।
अगर(x.Equals(y) && y.Equals(z))
true
, तोx.Equals(z)
true
लौटाताtrue
।संगत : यदि आप किसी ऑब्जेक्ट की तुलना कई बार करते हैं, तो परिणाम हमेशा समान होता है।
x.Equals(y)
क्रमिकx.Equals(y)
वापस आ जाते हैं जब तक x और y द्वारा संदर्भित ऑब्जेक्ट संशोधित नहीं होते हैं।अशक्त की तुलना : कोई भी वस्तु
null
बराबर नहीं है।
x.Equals(null)
false
देताfalse
।
GetHashCode
कार्यान्वयन:
Equals
साथ संगत : यदि दो वस्तुएं समान हैं (जिसका अर्थ है किEquals
रिटर्न सही है), तोGetHashCode
को उनमें से प्रत्येक के लिए समान मान वापस करना होगा ।बड़ी सीमा : यदि दो वस्तुएं समान नहीं हैं (
Equals
झूठ कहते हैं), उच्च संभावना होनी चाहिए कि उनके हैश कोड अलग हैं। परफेक्ट हैशिंग अक्सर संभव नहीं है क्योंकि चुनने के लिए सीमित संख्या में मान हैं।सस्ता : सभी मामलों में हैश कोड की गणना करना सस्ता होना चाहिए।
डिफ़ॉल्ट समान व्यवहार।
Object
क्लास में ही Equals
घोषित किए जाते हैं।
public virtual bool Equals(Object obj);
डिफ़ॉल्ट रूप से, Equals
व्यवहार में निम्न व्यवहार होते हैं:
यदि उदाहरण एक संदर्भ प्रकार है, तो
Equals
केवल तभी वापस आएंगे जब संदर्भ समान होंगे।यदि उदाहरण एक मान प्रकार है, तो
Equals
केवल तभी वापस आ जाएगा जब प्रकार और मान समान हों।string
एक विशेष मामला है। यह एक मूल्य प्रकार की तरह व्यवहार करता है।
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
//areFooClassEqual: False
Foo fooClass1 = new Foo("42");
Foo fooClass2 = new Foo("42");
bool areFooClassEqual = fooClass1.Equals(fooClass2);
Console.WriteLine("fooClass1 and fooClass2 are equal: {0}", areFooClassEqual);
//False
//areFooIntEqual: True
int fooInt1 = 42;
int fooInt2 = 42;
bool areFooIntEqual = fooInt1.Equals(fooInt2);
Console.WriteLine("fooInt1 and fooInt2 are equal: {0}", areFooIntEqual);
//areFooStringEqual: True
string fooString1 = "42";
string fooString2 = "42";
bool areFooStringEqual = fooString1.Equals(fooString2);
Console.WriteLine("fooString1 and fooString2 are equal: {0}", areFooStringEqual);
}
}
public class Foo
{
public string Bar { get; }
public Foo(string bar)
{
Bar = bar;
}
}
}
एक अच्छा GetHashCode ओवरराइड लिखना
GetHashCode
का डिक्शनरी <और> हैशटेबल पर प्रमुख प्रदर्शन प्रभाव है।
अच्छा GetHashCode
तरीके
- एक समान वितरण होना चाहिए
- प्रत्येक पूर्णांक में यादृच्छिक उदाहरण के लिए लौटने की लगभग समान संभावना होनी चाहिए
- यदि आपकी विधि प्रत्येक उदाहरण के लिए एक ही पूर्णांक (उदाहरण के लिए स्थिर '999') लौटाती है, तो आपके पास खराब प्रदर्शन होगा
- जल्दी होना चाहिए
- ये क्रिप्टोग्राफिक हैश नहीं हैं, जहां सुस्ती एक विशेषता है
- अपने हैश फ़ंक्शन को धीमा करें, अपने शब्दकोश को धीमा करें
- समान HashCode को दो उदाहरणों पर वापस करना चाहिए जो
Equals
सच का मूल्यांकन करता है- यदि वे नहीं करते (उदाहरण के लिए
GetHashCode
एक यादृच्छिक संख्या देता है), तो आइटम एकList
,Dictionary
, या समान में नहीं मिल सकते हैं।
- यदि वे नहीं करते (उदाहरण के लिए
GetHashCode
को कार्यान्वित करने के लिए एक अच्छी विधि एक प्राइम नंबर को एक शुरुआती मूल्य के रूप में उपयोग करना है, और उस प्रकार के फ़ील्ड के हैशकोड को अन्य प्राइम संख्याओं से गुणा करना है:
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 3049; // Start value (prime number).
// Suitable nullity checks etc, of course :)
hash = hash * 5039 + field1.GetHashCode();
hash = hash * 883 + field2.GetHashCode();
hash = hash * 9719 + field3.GetHashCode();
return hash;
}
}
केवल फ़ील्ड्स जो Equals
मेथोड में उपयोग किए जाते हैं, उन्हें हैश फ़ंक्शन के लिए उपयोग किया जाना चाहिए।
यदि आपको शब्दकोश / हैशटेबल्स के लिए अलग-अलग तरीकों से एक ही प्रकार का इलाज करने की आवश्यकता है, तो आप IEqualityComparer का उपयोग कर सकते हैं।
कस्टम प्रकार पर बराबरी और GetHashCode ओवरराइड करें
एक वर्ग Person
जैसे:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Clothes { get; set; }
}
var person1 = new Person { Name = "Jon", Age = 20, Clothes = "some clothes" };
var person2 = new Person { Name = "Jon", Age = 20, Clothes = "some other clothes" };
bool result = person1.Equals(person2); //false because it's reference Equals
लेकिन Equals
और GetHashCode
को GetHashCode
निम्नानुसार है:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Clothes { get; set; }
public override bool Equals(object obj)
{
var person = obj as Person;
if(person == null) return false;
return Name == person.Name && Age == person.Age; //the clothes are not important when comparing two persons
}
public override int GetHashCode()
{
return Name.GetHashCode()*Age;
}
}
var person1 = new Person { Name = "Jon", Age = 20, Clothes = "some clothes" };
var person2 = new Person { Name = "Jon", Age = 20, Clothes = "some other clothes" };
bool result = person1.Equals(person2); // result is true
इसके अलावा व्यक्तियों पर अलग-अलग प्रश्न बनाने के लिए LINQ का उपयोग करना Equals
और GetHashCode
दोनों की जांच करेगा:
var persons = new List<Person>
{
new Person{ Name = "Jon", Age = 20, Clothes = "some clothes"},
new Person{ Name = "Dave", Age = 20, Clothes = "some other clothes"},
new Person{ Name = "Jon", Age = 20, Clothes = ""}
};
var distinctPersons = persons.Distinct().ToList();//distinctPersons has Count = 2
IE इक्वलिटी कॉमपैरेटर में बराबर और गेटहैशकोड
दिए गए प्रकार के लिए Person
:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Clothes { get; set; }
}
List<Person> persons = new List<Person>
{
new Person{ Name = "Jon", Age = 20, Clothes = "some clothes"},
new Person{ Name = "Dave", Age = 20, Clothes = "some other clothes"},
new Person{ Name = "Jon", Age = 20, Clothes = ""}
};
var distinctPersons = persons.Distinct().ToList();// distinctPersons has Count = 3
लेकिन एक IEqualityComparator
में Equals
और IEqualityComparator
को GetHashCode
करना:
public class PersonComparator : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return x.Name == y.Name && x.Age == y.Age; //the clothes are not important when comparing two persons;
}
public int GetHashCode(Person obj) { return obj.Name.GetHashCode() * obj.Age; }
}
var distinctPersons = persons.Distinct(new PersonComparator()).ToList();// distinctPersons has Count = 2
ध्यान दें कि इस क्वेरी के लिए, दो ऑब्जेक्ट्स को समान माना गया है यदि दोनों Equals
सही हैं और GetHashCode
ने दोनों व्यक्तियों के लिए समान हैश कोड लौटाया है।