2012-05-24 31 views
14

मेरे पास एक PagedModel क्लास है जो पेजिंग डेटा को अनदेखा करने के लिए केवल मॉडलडेटा को वापस करने के लिए IENumerable लागू करता है। मैंने बराबर और GetHashCode को दो मॉडल किए गए मॉडेल ऑब्जेक्ट्स को उनके मॉडलडेटा, पेज नम्बर, और टोटलपेज और पेजसाइज द्वारा तुलना करने की अनुमति देने के लिए ओवरराइड किया है।Assert.AreEqual मेरे इक्व्यूल्स का उपयोग नहीं करता है INumerable कार्यान्वयन

यहाँ समस्या

Dim p1 As New PagedModel() With { 
    .PageNumber = 1, 
    .PageSize = 10, 
    .TotalPages = 10, 
    .ModelData = GetModelData() 
} 

Dim p2 As New PagedModel() With { 
    .PageNumber = 1, 
    .PageSize = 10, 
    .TotalPages = 10, 
    .ModelData = GetModelData() 
} 

p1.Equals(p2) =====> True 
Assert.AreEqual(p1, p2) ======> False! 

यह NUnit की तरह लग रहा है, यह आंतरिक EnumerableEqual विधि है तुलना करने के लिए बुला रहा है मेरी PagedModel के बजाय तरीकों मैं प्रदान की बराबर का उपयोग करने का! क्या इस व्यवहार को ओवरराइड करने का कोई तरीका है, या मुझे कस्टम दावा लिखना है।

उत्तर

9

कर क्या आप पूछ रहे हैं: मैं इसे के खिलाफ सलाह लेकिन तुम सच में NUnit के व्यवहार पसंद नहीं है, तो और जोर आप अपने खुद के EqualityComparer प्रदान कर सकते हैं अनुकूलित करने के लिए चाहते हैं।

Assert.That(p1, Is.EqualTo(p2).Using(myCustomEqualityComparer)); 

तुम क्या कर किया जाना चाहिए (संक्षिप्त उत्तर): आप GetHashCode की जरूरत है और PagedModel के बजाय ModelData पर बराबर होती है क्योंकि आप संग्रह और ModelData तत्व के रूप में के रूप में PagedModel उपयोग कर रहे हैं। इसके बजाय PagedModel पर Equals(object) अधिभावी की आप ModelData, जहां टी IEnumerable के प्रकार पैरामीटर है, साथ ही ओवरराइड GetHashCode() के रूप में पर IEquatable<T> लागू करने की आवश्यकता :

आप क्या करना चाहिए क्या (लांग जवाब)Default Equality Comparer (आप अपना खुद का IEqualityComparer निर्दिष्ट नहीं करते हैं) का उपयोग करते समय इन दो तरीकों से .NET उपयोग में समानता निर्धारित करने के लिए .NET उपयोग (यूनियन, डिस्टिंट इत्यादि जैसे संचालन के लिए) है।

[डिफ़ॉल्ट समानता comparer] चेकों प्रकार टी System.IEquatable इंटरफ़ेस लागू करता है और, यदि ऐसा है तो, एक EqualityComparer कि कार्यान्वयन का उपयोग करता है देता है। अन्यथा, यह एक EqualityComparer Object.Equals और Object.GetHashCode की ओवरराइड टी


द्वारा प्रदान का उपयोग करता है सही ढंग से कार्य करने के लिए देता है, GetHashCode सभी वस्तुओं है कि .Equals के लिए सच लौटने के लिए एक ही परिणाम वापस करने की जरूरत है (टी)। रिवर्स जरूरी नहीं है - GetHashCode उन वस्तुओं के लिए टकराव वापस कर सकता है जो बराबर नहीं हैं। More information here - see Marc Gravel's accepted answer। मुझे प्राइम्स का उपयोग करके उस उत्तर में GetHashCode का कार्यान्वयन भी बहुत उपयोगी पाया गया है।

+0

यह उत्तर क्या कह रहा है कि अनिवार्य रूप से आपके कार्यान्वयन में आपको IEquatable स्पष्ट रूप से कार्यान्वित करने की आवश्यकता है ... देखें http://stackoverflow.com/questions/1577149/explicit-interface-implementation-in-vb-net – Jay

+0

नहीं, IEquatable लागू करना पर्याप्त नहीं है। GetHashCode कार्यान्वयन उतना ही महत्वपूर्ण है। यह समझना भी महत्वपूर्ण है कि यदि आप IEquatable (मेरी पोस्ट में उद्धरण देखें) को लागू नहीं करते हैं तो इक्व्यूमेबल फॉल्स-बैक बैक-बैक (ऑब्जेक्ट) का उपयोग करने के लिए वापस आते हैं, इसलिए ऐसा करने की बिल्कुल आवश्यकता नहीं है। – csauve

+0

मैंने स्पष्ट रूप से IEquatable.Equals को लागू करने के लिए कहा जो डिफ़ॉल्ट फॉलबैक की अनुमति नहीं देनी चाहिए क्योंकि विधि ओवरराइड हो जाएगी और स्पष्ट रूप से कार्यान्वयन विधि को कॉल करेगा ... – Jay

1

आप GIT repo में NUnit समानता comparer के कार्यान्वयन पर एक नज़र डालें, तो आप जो एक उच्च प्राथमिकता है (क्योंकि यह उच्च रखा गया है दो enumerations के लिए एक समर्पित तुलना ब्लॉक, है कि वहाँ देखेंगे) comparisons से IEquatable<T> इंटरफ़ेस या Object.Equals(Object) विधि का उपयोग करके, जिसे आपने अपने PagedModel कक्षा में लागू या ओवरलोड किया है।

अगर यह एक बग या एक विशेषता है मैं नहीं जानता, लेकिन आप शायद, पहले अपने आप से पूछना चाहिए कि क्या आपका PagedModel वर्ग द्वारा IEnumerable<ModelData> इंटरफेस को लागू करने के लिए सीधे वास्तव में सबसे अच्छा विकल्प है, विशेष रूप से, क्योंकि आपके PagedModel की तुलना में अधिक कुछ है बस ModelData उदाहरणों का एक गणना।

शायद यह वर्ग की एक साधारण पढ़ने-योग्य IEnumerable<ModelData> संपत्ति के माध्यम से ModelData गणना प्रदान करने के लिए पर्याप्त (या इससे भी बेहतर) होगा। NUnit ऑब्जेक्ट को ModelData ऑब्जेक्ट्स की एक सरल गणना के रूप में देखने से रोक देगा और आपके यूनिट परीक्षण अपेक्षित व्यवहार करेंगे।

सीएसओवी द्वारा सुझाए गए एकमात्र अन्य विकल्प है; दावा है अपने PagedModel के लिए एक सरल कस्टम IComparer लागू करने के लिए और सभी के लिए यह का एक उदाहरण की आपूर्ति करने जहाँ आप दो PagedModel उदाहरणों की तुलना करेंगे:

internal class PagedModelComparer : System.Collections.IComparer 
{ 
    public static readonly IComparer Instance = new PagedModelComparer(); 

    private PagedModelComparer() 
    { 
    } 

    public int Compare(object x, object y) 
    { 
     return x is PagedModel && ((PagedModel)x).Equals(y); 
    } 
} 

    ... 
    [Test] 
    ... 
     Assert.That(actual, Is.EqualTo(expected).Using(PagedModelComparer.Instance)); 
    ... 

लेकिन इस आवश्यकता से अपने परीक्षणों और अधिक जटिल कर देगा और आप हमेशा करना होगा जब भी आप PagedModel के लिए अतिरिक्त परीक्षण लिख रहे हों तो अपने विशेष तुलनाकर्ता का उपयोग करने के लिए सोचें।