2009-06-07 22 views
8

हर बार जब मैं कुछ डेटा वर्ग लिखता हूं, तो मैं आमतौर पर आईक्वेटेबल कार्यान्वयन लिखने में इतना समय बिताता हूं।बराबर विधि कार्यान्वयन सहायक (सी #)

public class Polygon 
{ 
    public Point[] Vertices { get; set; } 
} 

कार्यान्वयन IEquatable exaustive था:

आखिरी वर्ग में मैंने लिखा की तरह कुछ था। निश्चित रूप से सी # 3.0/LINQ बहुत मदद करता है, लेकिन शिखर को स्थानांतरित किया जा सकता है और/या विपरीत क्रम में, और यह बराबर विधि में बहुत जटिलता जोड़ता है। कई यूनिट परीक्षणों के बाद, और इसी तरह के कार्यान्वयन के बाद, मैंने छोड़ दिया, और मेरे आवेदन को केवल त्रिकोण स्वीकार करने के लिए बदल दिया, जो आईक्वेटेबल कार्यान्वयन के लिए केवल 11 यूनिट परीक्षणों को पूरी तरह से कवर किया जाना आवश्यक था।

कोई उपकरण या तकनीक है जो बराबर और GetHashCode को लागू करने में मदद करती है?

+0

आप की तलाश में नहीं हो रहे हैं कोड पीढ़ी के बराबर है, लेकिन एक सामान्य एल्गोरिथ्म implementer के लिए। मुझे लगता है कि आप यहां भाग्य से बाहर हैं। – erikkallen

उत्तर

8

मैं समानता सदस्यों को उत्पन्न करने के लिए रीशेपर का उपयोग करता हूं। यदि आप चाहते हैं तो यह वैकल्पिक रूप से IEquatable<T> को ओवरराइड करने वाले ऑपरेटरों को लागू करेगा (जो निश्चित रूप से आप कभी नहीं करते हैं, लेकिन यह वैसे भी अच्छा है)।

बराबर के कार्यान्वयन में Object.Equals(Object) का ओवरराइड शामिल है, साथ ही दृढ़ता से टाइप किए गए संस्करण (जो अनावश्यक प्रकार की जांच से बच सकते हैं) शामिल हैं। कम टाइप किए गए संस्करण में एक प्रकार की जांच करने के बाद मजबूती से टाइप किया गया है। दृढ़ता से टाइप किया गया संस्करण संदर्भ समानता जांच (Object.ReferenceEquals(Object,Object)) करता है और फिर सभी फ़ील्ड के मानों की तुलना करता है (ठीक है, केवल वे जिन्हें आप जनरेटर को शामिल करने के लिए कहते हैं)।

GetHashCode का सवाल है, इस क्षेत्र की GetHashCode मूल्यों की एक स्मार्ट गुणनखंड (unchecked का उपयोग कर यदि आप संकलक के checked विकल्प का उपयोग अतिप्रवाह अपवाद से बचने के लिए) मिलाया जाता है। क्षेत्र के प्रत्येक मूल्य (पहले के अलावा) संयुक्त होने से पहले प्रमुख संख्याओं से गुणा किया जाता है। आप यह भी निर्दिष्ट कर सकते हैं कि कौन से फ़ील्ड कभी शून्य नहीं होंगे, और यह किसी भी शून्य जांच को छोड़ देगा।

यहाँ तुम क्या ALT+Insert दबाने फिर का चयन "उत्पन्न समानता सदस्य" करके अपने Polygon वर्ग के लिए प्राप्त होते हैं:

public class Polygon : IEquatable<Polygon> 
{ 
    public Point[] Vertices { get; set; } 

    public bool Equals(Polygon other) 
    { 
     if (ReferenceEquals(null, other)) return false; 
     if (ReferenceEquals(this, other)) return true; 
     return Equals(other.Vertices, Vertices); 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) return false; 
     if (ReferenceEquals(this, obj)) return true; 
     if (obj.GetType() != typeof (Polygon)) return false; 
     return Equals((Polygon) obj); 
    } 

    public override int GetHashCode() 
    { 
     return (Vertices != null ? Vertices.GetHashCode() : 0); 
    } 
} 

सुविधाओं के बारे में मैं ऊपर बात लागू नहीं है में से कुछ वहाँ केवल एक क्षेत्र के रूप में । ध्यान दें कि उसने सरणी की सामग्री की जांच नहीं की है।

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

+0

जादुई नहीं है लेकिन यह निश्चित रूप से मदद करता है! धन्यवाद –

+2

वह बराबर (ओबीजे) ओवरराइड मेरे लिए उत्कृष्ट कोड जैसा नहीं दिखता है। बस यह कहने के लिए और अधिक स्वाभाविक नहीं होगा कि यह वापस लौटाए। एक्वाल्स (पॉलीगॉन के रूप में ओबीजे) ;? – mquander

+0

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

2

वस्तुओं के दो सरणी की तुलना करने के लिए, मैं SequenceEqual एक्सटेंशन विधि का उपयोग करता हूं।

जेनेरिक इक्वाल्स और गेटहाशकोड के लिए, धारावाहिकता के आधार पर एक तकनीक है जो आपके लिए काम कर सकती है।

Using MemoryStream and BinaryFormatter for reuseable GetHashCode and DeepCopy functions

+0

इसे मेरे टूलसेट में जोड़ने के लिए धन्यवाद। –

+0

मुझे 3.5/System.Core.dll पर SequenceEqual नहीं मिला, क्या आप जानते हैं कि यह कहां है? मैं स्रोत कोड देखने के लिए रेड गेट के परावर्तक का उपयोग कर रहा हूं। –

+0

ग्रेट आलेख! अब मुझे एहसास हुआ कि बराबर कार्यान्वयन लिखना गूंगा है, आपको केवल गेटहाशकोड लागू करना है और फिर इसे बराबर पर उपयोग करना है। –

संबंधित मुद्दे