खोज…


टिप्पणियों

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 ने दोनों व्यक्तियों के लिए समान हैश कोड लौटाया है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow