जब वे समान वस्तु को लपेटते हैं तो क्या रैपर को == ऑपरेटर के बराबर उपयोग करना चाहिए?


19

मैं XML तत्वों के लिए एक आवरण लिख रहा हूं जो एक डेवलपर को XML से विशेषताओं को आसानी से पार्स करने की अनुमति देता है। आवरण में वस्तु लपेटे जाने के अलावा कोई स्थिति नहीं है।

मैं निम्नलिखित कार्यान्वयन (इस उदाहरण के लिए सरलीकृत) पर विचार कर रहा हूं जिसमें ==ऑपरेटर के लिए एक अधिभार शामिल है ।

class XmlWrapper
{
    protected readonly XElement _element;

    public XmlWrapper(XElement element)
    {
        _element = element;
    }

    public string NameAttribute
    {
        get
        {
            //Get the value of the name attribute
        }
        set
        {
            //Set the value of the name attribute
        }
    }

    public override bool Equals(object other)
    {
        var o = other as XmlWrapper;
        if (o == null) return false;
        return _element.Equals(o._element);
    }

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

    static public bool operator == (XmlWrapper lhs, XmlWrapper rhs)
    {
        if (ReferenceEquals(lhs, null) && ReferenceEquals(rhs, null)) return true;
        if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null)) return false;

        return lhs._element == rhs._element;
    }

    static public bool operator != (XmlWrapper lhs, XmlWrapper rhs)
    {
        return !(lhs == rhs);
    }
}

जैसा कि मैं मुहावरेदार ग # को समझता हूं, ==ऑपरेटर संदर्भ समानता के लिए है जबकि Equals()विधि मूल्य समानता के लिए है। लेकिन इस मामले में, "मूल्य" केवल वस्तु के लिपटे जाने का संदर्भ है। इसलिए मैं स्पष्ट नहीं हूं कि c # के लिए पारंपरिक या मुहावरेदार क्या है।

उदाहरण के लिए, इस कोड में ...

var underlyingElement = new XElement("Foo");
var a = new XmlWrapper(underlyingElement);
var b = new XmlWrapper(underlyingElement);

a.NameAttribute = "Hello";
b.NameAttribute = "World";

if (a == b)
{
    Console.WriteLine("The wrappers a and b are the same.");
}

.... क्या प्रोग्राम आउटपुट "रैपर a और b समान हैं"? या यह अजीब होगा, यानी कम से कम विस्मय के मूल का उल्लंघन ?


हर बार जब मैंने ओवररोड किया तो Equalsमैंने कभी भी ओवररोड नहीं किया ==(लेकिन कभी भी दूसरा रास्ता नहीं देखा)। आलसी मुहावरेदार है? अगर मुझे स्पष्ट कास्ट के बिना अलग व्यवहार मिलता है जो कम से कम विस्मय का उल्लंघन करता है।
राडारबॉब

इसका उत्तर इस बात पर निर्भर करता है कि NameAttribute क्या करता है - अंतर्निहित तत्व को संशोधित करता है? क्या डेटा का एक अतिरिक्त टुकड़ा है? उदाहरण कोड का अर्थ (और क्या इसे समान माना जाना चाहिए) इसके आधार पर परिवर्तन होते हैं, इसलिए मुझे लगता है कि आपको इसे भरने की आवश्यकता है।
Errorsatz

@Errorsatz मैं माफी माँगता हूँ, लेकिन मैं उदाहरण को संक्षिप्त रखना चाहता था, और मैंने माना कि यह स्पष्ट था कि यह लिपटे तत्व को संशोधित करेगा (विशेष रूप से "एक्सएमएल नाम" एक्सएमएल विशेषता को संशोधित करके), लेकिन बारीकियों में मुश्किल से बात है - बिंदु है। कि आवरण लिपटे हुए तत्व तक पढ़ने / लिखने की अनुमति देता है, लेकिन उसकी अपनी कोई स्थिति नहीं होती है।
जॉन वू

4
खैर, इस मामले में वे मायने रखते हैं - इसका मतलब है कि "हैलो" और "वर्ल्ड" असाइनमेंट भ्रामक है, क्योंकि बाद वाला पूर्व को अधिलेखित कर देगा। जिसका मतलब है कि मैं मार्टिन के जवाब से सहमत हूं कि दोनों को एक समान माना जा सकता है। यदि NameAttribute वास्तव में उनके बीच भिन्न थे, तो मैं उन्हें समान नहीं मानूंगा।
एरर्सजेटा

2
"जैसा कि मैं मुहावरेदार ग # को समझता हूं, == ऑपरेटर संदर्भ समानता के लिए है जबकि इक्वल्स () विधि मूल्य समानता के लिए है।" हालांकि यह है? ज्यादातर बार मैंने देखा == अतिभारित मूल्य समानता के लिए है। सबसे महत्वपूर्ण उदाहरण System.String है।
आर्टुरो टॉरेस सांचेज़

जवाबों:


17

चूंकि लिपटे XElementका संदर्भ अपरिवर्तनीय है XmlWrapper, इसलिए एक ही तत्व को लपेटने के दो उदाहरणों के बीच कोई बाहरी रूप से अवलोकन योग्य अंतर नहीं है , इसलिए यह ==इस तथ्य को प्रतिबिंबित करने के लिए अधिभार के लिए समझ में आता है।

क्लाइंट कोड लगभग हमेशा तार्किक समानता की परवाह करता है (जो कि डिफ़ॉल्ट रूप से, संदर्भ प्रकारों के लिए संदर्भ समानता का उपयोग करके लागू किया जाता है)। तथ्य यह है कि ढेर पर दो उदाहरण हैं एक कार्यान्वयन विवरण है जो ग्राहकों को परवाह नहीं करना चाहिए (और जो लोग Object.ReferenceEqualsसीधे उपयोग करेंगे )।


9

अगर आपको लगता है कि यह सबसे अधिक समझ में आता है

प्रश्न और उत्तर डेवलपर अपेक्षा का विषय है , यह कोई तकनीकी आवश्यकता नहीं है।

यदि आप एक रैपर को पहचान नहीं मानते हैं और इसे इसकी सामग्री द्वारा विशुद्ध रूप से परिभाषित किया गया है, तो आपके प्रश्न का उत्तर हां है।

लेकिन यह एक आवर्ती समस्या है। क्या दो रैपरों में समानता प्रदर्शित होती है जब वे विभिन्न वस्तुओं को लपेटते हैं लेकिन दोनों वस्तुओं के साथ समान सामग्री होती है?

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

यह सभी तरह से नीचे कछुए है


सामान्य टिप

जब भी आप डिफ़ॉल्ट व्यवहार से विचलित होते हैं, तो इसे स्पष्ट रूप से प्रलेखित किया जाना चाहिए। एक डेवलपर के रूप में, मुझे उम्मीद है कि दो संदर्भ प्रकार समानता प्रदर्शित नहीं करेंगे, भले ही उनकी सामग्री समान हो। यदि आप उस व्यवहार को बदल देते हैं, तो मैं आपको यह स्पष्ट रूप से प्रलेखित करने का सुझाव दूंगा ताकि सभी डेवलपर्स इस असामान्य व्यवहार से अवगत हों।


जैसा कि मैं मुहावरेदार ग # को समझता हूं, ==ऑपरेटर संदर्भ समानता के लिए है जबकि Equals()विधि मूल्य समानता के लिए है।

यह इसका डिफ़ॉल्ट व्यवहार है, लेकिन यह एक अचल नियम नहीं है। यह कन्वेंशन की बात है, लेकिन कन्विंस जहां बदले जा सकते हैं ।

stringयहाँ एक महान उदाहरण है, जैसा ==कि एक मूल्य समानता की जांच भी है (तब भी जब कोई स्ट्रिंग इंटर्निंग नहीं है!)। क्यों? सीधे शब्दों में कहें: क्योंकि स्ट्रिंग्स होने से वैसा ही व्यवहार होता है जैसे कि मूल्य अधिकांश डेवलपर्स के लिए अधिक सहज महसूस करते हैं।

यदि आपके रैपर (या आपके डेवलपर्स का जीवन) बोर्ड के पार आपके रैपर प्रदर्शन मूल्य समानता प्रदर्शित करके विशेष रूप से सरल बनाया जा सकता है, तो इसके लिए जाएं (लेकिन इसे दस्तावेज़ करें )।

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


मैं उत्सुक हूं कि आप क्यों अपेक्षा करते हैं कि संदर्भ प्रकार सामग्री समानता को परिभाषित नहीं करेंगे। अधिकांश प्रकार केवल समानता को परिभाषित नहीं करते हैं क्योंकि यह उनके डोमेन के लिए आवश्यक नहीं है, इसलिए नहीं कि वे संदर्भ समानता चाहते हैं
कैसाब्लांका

3
@ कासाब्लांका: मुझे लगता है कि आप "उम्मीद" (यानी आवश्यकता बनाम धारणा) की एक अलग परिभाषा की व्याख्या कर रहे हैं। दस्तावेज़ीकरण के बिना, मैं उम्मीद करता हूं (यानी मान) कि ==संदर्भ समानता के लिए जांचता है क्योंकि यह डिफ़ॉल्ट व्यवहार है। हालांकि, अगर ==वास्तव में मूल्य समानता के लिए जाँच करता है , तो मुझे उम्मीद है (अर्थात आवश्यकता है) कि यह स्पष्ट रूप से प्रलेखित है। I'm curious why you expect that reference types won't define content equality.वे इसे डिफ़ॉल्ट रूप से परिभाषित नहीं करते हैं , लेकिन इसका मतलब यह नहीं है कि यह नहीं किया जा सकता है। मैंने कभी नहीं कहा कि यह (या नहीं) किया जाना चाहिए, मैं बस उम्मीद नहीं करता (यानी मान लें) यह डिफ़ॉल्ट रूप से है।
फ्लटर

मैं देख रहा हूं कि आपका क्या मतलब है, स्पष्ट करने के लिए धन्यवाद।
कैसाब्लांका

2

आप मूल रूप से तार की तुलना कर रहे हैं, तो मुझे आश्चर्य होगा कि अगर एक ही XML सामग्री वाले दो रैपर को समान नहीं माना जाएगा, तो इसे बराबर या == का उपयोग करके जांचा जाए।

मुहावरेदार नियम संदर्भ प्रकार की वस्तुओं के लिए सामान्य रूप से समझ में आ सकता है, लेकिन मुहावरेदार अर्थों में तार विशेष हैं, आपको उन्हें मान के रूप में माना और माना जाता है, हालांकि तकनीकी रूप से वे संदर्भ प्रकार हैं।

आपका आवरण पोस्टफ़िक्स हालांकि भ्रम जोड़ता है। यह मूल रूप से "एक XML तत्व नहीं" कहता है। तो क्या मुझे इसे एक संदर्भ प्रकार के रूप में मानना ​​चाहिए? शब्दार्थ इससे कोई मतलब नहीं होगा। अगर क्लास का नाम XmlContent रखा जाए तो मुझे कम भ्रम होगा। यह संकेत देगा कि हम सामग्री के बारे में परवाह करते हैं, न कि तकनीकी कार्यान्वयन विवरण।


आप "एक स्ट्रिंग से निर्मित वस्तु" और "मूल रूप से एक स्ट्रिंग" के बीच सीमा कहां रखेंगे? यह बाहर एपीआई दृष्टिकोण से काफी अस्पष्ट परिभाषा लगता है। क्या एपीआई के उपयोगकर्ता को वास्तव में व्यवहार का अनुमान लगाने के लिए आंतरिक का अनुमान लगाना पड़ता है?
आर्थर हैवेलिस

वर्ग / वस्तु के @ आर्थर शब्दार्थ सुराग प्रदान करना चाहिए। और कभी-कभी यह सब स्पष्ट नहीं होता है, इसलिए यह सवाल है। वास्तविक मूल्य प्रकारों के लिए यह किसी के लिए भी स्पष्ट होगा। असली तार के लिए भी। प्रकार को अंततः यह बताना चाहिए कि क्या तुलना में सामग्री या वस्तु पहचान शामिल होनी चाहिए।
मार्टिन मैत
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.