2010-08-12 13 views
14

मैं निम्नलिखित कोड:दो नेट वस्तुओं है कि बराबर हैं नहीं कहते वे कर रहे हैं

object val1 = 1; 
object val2 = 1; 

bool result1 = (val1 == val2);//Equals false 
bool result2 = val1.Equals(val2); //Equals true 

कि के साथ क्या है? Equals() विधि के साथ जाने के लिए इसे ठीक करने का एकमात्र तरीका है?

+0

कहते हैं कि वे बराबर हैं लेकिन दो अलग-अलग उदाहरण –

+0

दोस्त, == और 2. दो अलग-अलग चीजें करते हैं। == ऑपरेटर यह देखने के लिए जांच करता है कि क्या val1 और val2 एक ही मेमोरी स्पेस (संदर्भ) पर कब्जा करते हैं। सामग्री समानता के लिए जांच करता है। – Icemanind

+5

आप 'object.Equals (ऑब्जेक्ट, ऑब्जेक्ट) 'स्थैतिक विधि का भी उपयोग कर सकते हैं, जो पहले' == 'ऑपरेटर का उपयोग करके ऑब्जेक्ट्स की तुलना करने का प्रयास करता है और फिर' ऑब्जेक्ट्स। एक्वाल्स (ऑब्जेक्ट) 'विधि का प्रयास करता है यदि दोनों पैरामीटर हैं अशक्त नहीं। कारण मैं इसका सुझाव देता हूं कि आपको ऑब्जेक्ट को कॉल करने से पहले शून्य की जांच करने की आवश्यकता नहीं है। एक्सेल (ऑब्जेक्ट, ऑब्जेक्ट) ', जबकि आप करते हैं तो आप ऑब्जेक्ट को कॉल करते हैं। एक्वाल्स (ऑब्जेक्ट)'। –

उत्तर

32

ऑपरेटर == स्थैतिक, आभासी नहीं है, इसलिए व्यवहार स्थिर प्रकार द्वारा निर्धारित होता है, न कि रनटाइम प्रकार। संदर्भ प्रकार की वस्तुओं पर डिफ़ॉल्ट== के लिए कार्यान्वयन संदर्भों की तुलना करना है (हालांकि प्रकार एक अलग व्यवहार को लागू कर सकते हैं, उदाहरण के लिए string)। आपके पास दो अलग-अलग वस्तुएं हैं और उनके पास समान संदर्भ नहीं है इसलिए == झूठी रिटर्न देता है।

समाधान, जैसा कि आप इंगित करते हैं, बराबर का उपयोग करना है। बराबर एक वर्चुअल विधि है। चूंकि value1 में रनटाइम प्रकार Int32 है, तो आप Int32.Equals पर कॉल करना समाप्त कर देते हैं। नेट परावर्तक से आप देख सकते हैं इस प्रकार है कि इस के कार्यान्वयन:

public override bool Equals(object obj) 
{ 
    return ((obj is int) && (this == ((int) obj))); 
} 

दूसरे शब्दों में, यह जाँच करता है, तो तर्क प्रकार int की है, और इसलिए यह डाले और == कि के लिए परिभाषित किया गया है का उपयोग करता है int। यह पूर्णांक के मान की तुलना करता है।

Equals() विधि के साथ जाने के लिए इसे ठीक करने का एकमात्र तरीका है?

एक वैकल्पिक Int32.Equals के कार्यान्वयन करता है बस के रूप में, int करने के लिए अपने वस्तुओं डाली और फिर == उपयोग करने के लिए है।

+0

यह एकमात्र सही उत्तर प्रतीत होता है (या, कम से कम, मुझे यकीन है कि आप स्ट्रिंग पर == का उपयोग कर सकते हैं और इसे अपेक्षित रूप से काम कर सकते हैं)। –

+1

ठीक है, मुझे समझ में नहीं आता क्यों * बराबर * यहां काम करता है। दस्तावेज़ों के मुताबिक http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx "* बराबर का डिफ़ॉल्ट कार्यान्वयन * संदर्भ प्रकारों के लिए संदर्भ समानता का समर्थन करता है, और मूल्य प्रकारों के लिए बिटवाई समानता का समर्थन करता है। संदर्भ समानता का अर्थ ऑब्जेक्ट है जिन संदर्भों की तुलना की जाती है वे वही * ऑब्जेक्ट * देखें। " –

+0

@ जॉन सी: अच्छा सवाल। क्या मेरा अद्यतन उत्तर इसे स्पष्ट बनाता है? –

10

हां। == संदर्भ समानता के लिए जांच करता है। Equals का उपयोग करें जहां आप सामग्री की तुलना करना चाहते हैं।

आप सोच रहे होंगे कि यह ऑब्जेक्ट्स के साथ क्यों है। जब आप एक ऑब्जेक्ट वैरिएबल में एक पूर्णांक (मान प्रकार) सेट करते हैं, तो बॉक्सिंग नामक एक ऑपरेशन होता है। यह ऑपरेशन किसी ऑब्जेक्ट में मान प्रकार को लपेटता है और इसे ढेर पर रखता है और एक संदर्भ देता है। यह दो बार होता है और संदर्भ अलग हो जाते हैं (हालांकि मान समान हैं)।

1

ऐसा इसलिए है क्योंकि जब आप उन्हें ऑब्जेक्ट्स पर डालते हैं तो वे int मानों के संदर्भ में "रूपांतरित" होते हैं। और दो संदर्भ बराबर नहीं हैं। लेकिन बराबर संदर्भों के बजाय संदर्भित मानों की तुलना करता है।

0

दो ऑब्जेक्ट बराबर हैं यदि वे स्मृति में एक ही स्थान को इंगित करते हैं।

val1 == val1; //Equals true 

टीसी द्वारा इंगित किया गया है कि आप एक ऑपरेटर ओवरलोड कर सकते हैं।

public static bool operator ==(Object a, Object b) 

इस तरह ऑपरेटर == के व्यवहार इस विधि द्वारा परिभाषित किया जाएगा।

जब आप == ओवरलोड करते हैं तो आपको ऑपरेटर != भी अधिभारित करना चाहिए।

+1

जब तक एक ऑपरेटर अधिभार नहीं होता है। –

+0

@tc ने मेरे anwser को सही किया। धन्यवाद। –

2

== जांचता है कि क्या दो ऑब्जेक्ट समान हैं। वो नहीं हैं।वे एक ही संख्या का प्रतिनिधित्व करते हैं, लेकिन स्मृति में विभिन्न स्थानों पर संग्रहीत हैं।

यह दो सेब की तुलना करना है। दोनों सेब और समान दिखते हैं, लेकिन वे अलग-अलग वस्तुएं हैं।

0

आप object लेकिन एक कस्टम वर्ग उपयोग नहीं कर रहे हैं, तो आप == ऑपरेटरों ओवरराइड कर सकते हैं और! =, और शायद IEqualityComparer<T> इंटरफ़ेस को लागू करना चाहिए

public static bool operator ==(MyType left, MyType right) 
{ 
    //code here, don't forget about NULLS when writing comparison code!!! 
} 

public static bool operator !=(MyType left, MyType right) 
{ 
    return !(left == right); 
} 

public bool Equals(MyType x, MyType y) 
{ 
    return (x == y); 
} 

public int GetHashCode(MyType obj) 
{ 
    return base.GetHashCode(); 
} 
0

CIL अपने कोड बक्से दो पूर्णांकों के लिए और मुक्केबाजी (==) के परिणामस्वरूप दो वस्तुओं की तुलना करता है। यह तुलना संदर्भ द्वारा है।

.locals init ([0] object val1, 
      [1] object val2, 
      [2] bool result1, 
      [3] bool result2) 
    IL_0000: nop 
    IL_0001: ldc.i4.1 
    IL_0002: box  [mscorlib]System.Int32 
    IL_0007: stloc.0 
    IL_0008: ldc.i4.1 
    IL_0009: box  [mscorlib]System.Int32 
    IL_000e: stloc.1 
    IL_000f: ldloc.0 
    IL_0010: ldloc.1 
    IL_0011: ceq 
    IL_0013: stloc.2 
    IL_0014: ldloc.0 
    IL_0015: ldloc.1 
    IL_0016: callvirt instance bool [mscorlib]System.Object::Equals(object) 
    IL_001b: stloc.3 

.Equals यह Object.Equals कहता है, जो Int32.Equals कॉल (वस्तु पर आभासी विधि कॉल) के लिए:

public override bool Equals(object obj) 
{ 
    return ((obj is int) && (this == ((int) obj))); 
} 

इस int करने के लिए डाले और पूर्णांक के रूप में मूल्यों की तुलना, एक मूल्य तुलना तुलना करें।