सवाल ओवरलोडिंग ऑपरेटर == बनाम बराबर ()


मैं एक सी # प्रोजेक्ट पर काम कर रहा हूं जिस पर अब तक, मैंने अपरिवर्तनीय वस्तुओं और कारखानों का उपयोग यह सुनिश्चित करने के लिए किया है कि प्रकार की वस्तुएं Foo हमेशा समानता के लिए तुलना की जा सकती है ==

Foo वस्तुओं को एक बार बनाया नहीं जा सकता है, और फैक्ट्री हमेशा तर्क के दिए गए सेट के लिए एक ही ऑब्जेक्ट देता है। यह बहुत अच्छा काम करता है, और कोड आधार के दौरान हम इसे मानते हैं == हमेशा समानता की जांच के लिए काम करता है।

अब मुझे कुछ कार्यक्षमता जोड़ने की जरूरत है जो एक एज केस पेश करता है जिसके लिए यह हमेशा काम नहीं करेगा। करने के लिए सबसे आसान बात अधिभार है operator == उस प्रकार के लिए, ताकि परियोजना में किसी भी अन्य कोड को बदलने की जरूरत न हो। लेकिन यह मुझे एक कोड गंध के रूप में हमला करता है: अधिभार operator == और नहीं Equals बस अजीब लगता है, और मैं इस सम्मेलन में उपयोग किया जाता है कि == संदर्भ समानता की जांच करता है, और Equals वस्तु समानता की जांच करता है (या जो भी शब्द है)।

क्या यह एक वैध चिंता है, या मुझे आगे बढ़ना चाहिए और अधिभार करना चाहिए operator ==?


41
2017-11-19 21:00


मूल


संयोग से, vb.net इसके उपयोग को रोकता है = तथा <> समानता ऑपरेटरों प्रकार के लिए जो स्पष्ट अधिभार प्रदान नहीं करते हैं; संदर्भ समानता की जांच करने के लिए, एक उपयोग करता है Is या IsNot, जो अनिवार्य रूप से <i> हमेशा </ i> संदर्भ समानता की जांच करता है (मुख्य अपवाद तब होता है जब शून्य प्रकारों की तुलना में Nothing)। - supercat


जवाब:


मेरा मानना ​​है कि मानक यह है कि अधिकांश प्रकार के लिए, एक्वाल्स ऑब्जेक्ट समानता और ऑपरेटर की जांच करता है == संदर्भ समानता की जांच करता है।

मेरा मानना ​​है कि सबसे अच्छा अभ्यास यह है कि अपरिवर्तनीय प्रकार, ऑपरेटर के लिए == समानता के साथ-साथ साथ ही जांच करनी चाहिए .Equals। और यदि आप जानना चाहते हैं कि वे वास्तव में एक ही वस्तु हैं, तो उपयोग करें .ReferenceEquals। सी # देखें String इस के उदाहरण के लिए कक्षा।


27
2017-11-19 21:07



नहीं। संदर्भ प्रकारों के लिए 'मानक' दोनों बराबर en == दोनों के लिए refernceEquals के रूप में लौटने के लिए है। यह गैर-अपरिवर्तनीय प्रकारों के लिए या तो अधिभारित करने के लिए निराश है। - Henk Holterman
इसके अलावा, यहां नल से सावधान रहें। एक्स। एक्वाल्स (शून्य) एक्स एनआरआर फेंक देगा यदि एक्स शून्य है, जबकि शून्य == एक्स काम करेगा। - darthtrevino
'मानक' कुछ प्रकार की समस्या को हल करने का एक आम तरीका है, यदि 'मानक' रास्ते में आता है, तो यह बहुत अच्छा मानक नहीं है। - Bill Yang
बिल, लेकिन यह एक बहुत अच्छा मानक है। क्या आप एक प्रकार चाहते हैं a != b लेकिन संग्रह वर्गों को लगता है कि वे डुप्लिकेट हैं? - Henk Holterman
@ बिल, मैं मानक का पालन न करके थोड़ा सा हो गया। यही कारण है कि मैं पूछ रहा हूं कि यह ठीक है। यह इतना संकेत होना चाहिए कि मानक महत्वपूर्ण है। कोडिंग शैली मानकों (जो समूह के भीतर पठनीयता को बढ़ावा देने के लिए हैं) और व्यावहारिक कोडिंग मानकों (जो बहुत सारे सिरदर्द से बचते हैं) के बीच एक अंतर है। - Lee Louviere


बीच में एक बड़ा अंतर है अधिक भार  == तथा अधिभावी बराबर होती है।

जब आपके पास अभिव्यक्ति हो

if (x == y) {

वेरिएबल्स एक्स और वाई की तुलना करने के लिए उपयोग की जाने वाली विधि का निर्णय लिया जाता है संकलन पहर। यह ऑपरेटर ओवरलोडिंग है। X और y घोषित करते समय उपयोग किया जाने वाला प्रकार यह निर्धारित करने के लिए उपयोग किया जाता है कि उनकी तुलना करने के लिए किस विधि का उपयोग किया जाता है। एक्स और वाई (यानी, सबक्लास या इंटरफ़ेस कार्यान्वयन) के भीतर वास्तविक प्रकार अप्रासंगिक है। निम्नलिखित को धयान मे रखते हुए।

object x = "hello";
object y = 'h' + "ello"; // ensure it's a different reference

if (x == y) { // evaluates to FALSE

और निम्नलिखित

string x = "hello";
string y = 'h' + "ello"; // ensure it's a different reference

if (x == y) { // evaluates to TRUE

यह दर्शाता है कि चर x और y को घोषित करने के लिए उपयोग किया जाने वाला प्रकार यह निर्धारित करने के लिए किया जाता है कि == का मूल्यांकन करने के लिए किस विधि का उपयोग किया जाता है।

तुलनात्मक रूप से, बराबर निर्धारित किया जाता है क्रम परिवर्तनीय एक्स के भीतर वास्तविक प्रकार के आधार पर। बराबर ऑब्जेक्ट पर वर्चुअल विधि है जो अन्य प्रकार कर सकते हैं, और कर सकते हैं, ओवरराइड कर सकते हैं। इसलिए निम्नलिखित दो उदाहरण सत्य दोनों का मूल्यांकन करते हैं।

object x = "hello";
object y = 'h' + "ello"; // ensure it's a different reference

if (x.Equals(y)) { // evaluates to TRUE

और निम्नलिखित

string x = "hello";
string y = 'h' + "ello"; // ensure it's a different reference

if (x.Equals(y)) { // also evaluates to TRUE

82
2017-12-04 19:56



यह एक बहुत ही महत्वपूर्ण बात है, और यह कुछ ऐसा है जो मैं बाद में आया था, जबकि मैं इसका परीक्षण कर रहा था। चूंकि मुझे जरूरी था operator== रन-टाइम प्रकार पर निर्भर रहने के लिए, मैंने बेस क्लास में एक ऑपरेटर ओवरलोड को परिभाषित किया जिसे बुलाया गया था Equals()। एक जादू की तरह काम किया। (तब मैंने ऑब्जेक्ट मॉडल को रेडिड किया और पूरी चीज़ को तोड़ दिया। लेकिन यह एक अलग कहानी है।) - JSBձոգչ
मैं पूरी तरह से असहमत हूँ। का उपयोग == एक आम मुहावरे है। सिर्फ इसलिए कि सी # सभी इकाइयों को आधार देता है object इसका मतलब यह नहीं है कि हमें इस पद की स्थिति को रोकने के लिए मुहावरे को त्यागना चाहिए। इसके बजाय, यह उपयोग करने के लिए अच्छा अभ्यास बन जाता है .Equals() पदानुक्रम के शीर्ष पर तुलना की आवश्यकता होने पर। - drdwilcox
संक्षेप में, अधिभार == को सेट करने के लिए कौन सी विधि सेट करें (ऑब्जेक्ट। एक्वाल्स, या ऑब्जेक्ट। रेफरेंस एक्वाल)। अधिभार ऑब्जेक्ट। वास्तविक मूल्य समानता की जांच करने के लिए आवश्यक है। क्या मैं सही हू? - Lee Louviere
@Xaade, के लिए अलग व्यवहार होने के बाद '' तथा Equals बहुत खतरनाक आईएमओ है। उन्हें एक ही काम करने के लिए प्रोग्राम किया जाना चाहिए और आप विभिन्न कार्यान्वयन प्रदान कर सकते हैं IEqualityComparer वैकल्पिक बराबर कार्यान्वयन की पेशकश करने के लिए। - Samuel Neff
वाह, यह .NET के डिजाइन में एक डरावना मुर्गा है। यह विचार कि दो स्ट्रिंग्स बराबर नहीं होंगे क्योंकि मैंने स्ट्रिंग एक्स की बजाय ऑब्जेक्ट एक्स का उपयोग किया है, मेरे चर को परिभाषित करने के लिए एक पुरस्कार-ग्रेड कोड गंध है। यह बहुत अच्छी तरह से समझाने के लिए धन्यवाद। - David Arno


यह निश्चित रूप से बदबू आ रही है। अधिभार जब == आपको यह सुनिश्चित करना चाहिए कि दोनों Equals() तथा GetHashCode() भी सुसंगत हैं। देखें एमएसडीएन दिशानिर्देश

और यह एकमात्र कारण है कि यह बिल्कुल ठीक लगता है कि आप अपने प्रकार को अपरिवर्तनीय मानते हैं।


7
2017-11-19 22:13



मैं एक methodinfo में एक विशेषता की तुलना कर रहा हूँ। वे semantically अपरिवर्तनीय हैं। - Lee Louviere


अपरिवर्तनीय प्रकारों के लिए मुझे नहीं लगता कि इसमें कुछ भी गलत है == मूल्य समानता का समर्थन करने के लिए अधिभारित। मुझे नहीं लगता कि मैं ओवरराइड करूंगा == बिना ओवरराइड के Equals हालांकि वही अर्थशास्त्र है। यदि आप ओवरराइड करते हैं == और किसी कारण से संदर्भ समानता की जांच करने की आवश्यकता है, आप इसका उपयोग कर सकते हैं Object.ReferenceEquals(a,b)

यह देखो कुछ उपयोगी दिशानिर्देशों के लिए माइक्रोसॉफ्ट लेख


7
2017-11-19 21:15



केवल एक अच्छा विचार अगर अपरिवर्तनीय प्रकार भी सील किया जाता है। यदि प्रकार को उप-वर्गीकृत किया जा सकता है, तो यह सबसे खेदजनक है कि जिसे "==" कहा जाता है जिसे COMPILE-TIME परिवर्तनीय घोषणा द्वारा निर्धारित किया जाता है, गतिशील प्रकार द्वारा रन-टाइम पर नहीं (जो सबक्लास हो सकता है)। - ToolmakerSteve


नमूना दिखा रहा है कि इसे कैसे कार्यान्वित किया जाए एमएसएफटी दिशानिर्देश (नीचे)। ध्यान दें, जब बराबर ओवरराइड करते हैं तो आपको GetHashCode () को ओवरराइड करने की भी आवश्यकता होती है। उम्मीद है कि यह लोगों की मदद करता है।

public class Person
{
    public Guid Id { get; private set; }

    public Person(Guid id)
    {
        Id = id;
    }

    public Person()
    {
        Id = System.Guid.NewGuid();
    }

    public static bool operator ==(Person p1, Person p2)
    {
        bool rc;

        if (System.Object.ReferenceEquals(p1, p2))
        {
            rc = true;
        }
        else if (((object)p1 == null) || ((object)p2 == null))
        {
            rc = false;
        }
        else
        {
            rc = (p1.Id.CompareTo(p2.Id) == 0);
        }

        return rc;
    }

    public static bool operator !=(Person p1, Person p2)
    {
        return !(p1 == p2);
    }

    public override bool Equals(object obj)
    {
        bool rc = false;
        if (obj is Person)
        {
            Person p2 = obj as Person;
            rc = (this == p2);
        }
        return rc;
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

5
2018-02-09 23:45



आपकी शून्य जांच त्रुटिपूर्ण है। अगर दोनों लोगों के शून्य हैं जब यह सच होना चाहिए जब यह झूठी वापसी होगी। आप एक बूलियन OR के बजाय एक अनन्य या दो शून्य जांच के बीच उपयोग करना चाहते हैं। - Servy
यदि संदर्भ पी 1 और पी 2 शून्य हैं तो संदर्भ एक्वाल्स सच हो जाएंगे। इसलिए बुलियन या कोड कभी निष्पादित नहीं होगा और ऑपरेटर अपेक्षित के रूप में सत्य वापस आ जाएगा। - friederbluemle
बीटीडब्लू, आपकी कोडिंग शैली काम नहीं करेगी अगर व्यक्ति को उप-वर्गीकृत किया जा सकता है। इसके बजाए, तर्क को "बराबर" विधि में रखें, और ऑपरेटर "==" ऑब्जेक्ट को कॉल करें। एक्वाल्स (ए, बी)। कारण: जो "==" कॉल किया जाता है, वह डायनामिक प्रकार के बजाय COMPILE-TIME प्रकार पर आधारित होता है। ऑब्जेक्ट। एक्वाल्स गतिशील रूप से प्रेषण करता है। यदि व्यक्ति उप-वर्गीकृत है, तो केवल व्यक्तियों को डालने के लिए, प्रकारों की तुलना करना भी जरूरी है। "बराबर" के सही कोडिंग का एक उदाहरण यहां है। msdn.microsoft.com/en-us/library/336aedhh(v=vs.85).aspx  "GetType ()! = Obj.GetType ()) का निरीक्षण करें"। उप-वर्ग मौजूद होने पर यह आवश्यक है। - ToolmakerSteve
@ToolmakerSteve: लेकिन बनाना == अन्य सभी ऑपरेटरों से अलग-अलग कार्य करना इतना अच्छा नहीं है कि डिजाइन ... या तो पॉलिमॉर्फिक संदर्भों के साथ ऑपरेटरों को संयोजित करते समय देखभाल की आवश्यकता होती है। - Ben Voigt


माइक्रोस्कोफ्ट्स के मुताबिक बराबर प्रथाओं का परिणाम बराबर विधि के परिणाम और बराबर (==) अधिभार समान होना चाहिए।

सीए 2224: ऑपरेटर बराबर ओवरलोडिंग पर बराबर ओवरराइड


4
2017-09-21 08:32



लगभग सभी परिस्थितियों में जहां एक स्थिर रूप से बाध्य होता है == एक वर्चुअल ओवरराइड भी करना चाहिए Equals सदस्य, लेकिन रिवर्स सच नहीं है। केवल एक अधिभार चाहिए == के लिये सील प्रकार जो मूल्यों की तरह बहुत व्यवहार करते हैं (रास्ता String करता है), लेकिन एक को अक्सर ओवरराइड करना चाहिए Equals असीमित प्रकार के लिए। ध्यान दें कि बहुत से प्रोग्रामर उम्मीद करते हैं कि आवेदन कर रहे हैं == ऑपरेटर के अलावा किसी भी वर्ग प्रकार के लिए string संदर्भ-समानता की जांच के लिए एक लघुरूप है। - supercat