2013-08-21 7 views
5

क्यों काम नहीं करता है मेरे पास पृष्ठ नामक एक ऑब्जेक्ट है, जिसे पी कहा जाता है जिसमें एसोसिएटेड एट्रिब्यूट्स नामक एक कस्टम प्रॉपर्टी है। अगर मैं निम्न कार्य करें:क्या कोई मुझे LINQ के अंतर को सही ढंग से समझा सकता है? मुझे समझ में नहीं आता कि यह

int numMatchingAttributes = p.AssociatedAttributes.Intersect(p.AssociatedAttributes).Distinct().Count(); 

numMatchingAttributes भले ही पी 6 AssociatedAttributes है 0 के बराबर समाप्त होता है। यह 6 के बराबर क्यों नहीं है?

AssociatedAttributes प्रकार List<Attribute> की है (Attribute, मेरे अपने वर्ग है System.Attribute नहीं) और AttributeIComparable<Attribute> लागू करता है, मैं, मैं इसे लागू IEquatable नहीं था चाहिए?

public int CompareTo(Attribute other) 
{ 
    return Id.CompareTo(other.Id); 
} 

Id प्रकार Guid की है:

इस विशेषता में CompareTo का कार्यान्वयन है।

इस

पृष्ठ पर AssociatedAttributes संपत्ति है:

public List<Attribute> AssociatedAttributes 
     { 
     get 
      { 
      List<Attribute> list = new List<Attribute>(); 
      using (
       PredictiveRecommendor dbContext = 
        new PredictiveRecommendor()){ 
       if (dbContext != null) 
        { 
        IQueryable<Attribute> query = from a in dbContext.PageAttributes 
                where a.Page.Id.Equals(this.Id) 
                select a.Attribute; 
        list = query.ToList(); 


        } 
       } 
      return list; 
      } 
     } 

(dbContext है एक Telerik OpenAccess संदर्भ)

अद्यतन:

: पेज में निम्न विधि है: यहाँ क्या काम कर समाप्त हो गया है
public int numberOfIntersectedAssociatedAttributes (Page other) 
     { 
     using (PredictiveRecommendor dbContext = new PredictiveRecommendor()) 
      { 
      IQueryable<Attribute> thisAssocAttributes = from a in dbContext.PageAttributes 
                 where a.Page.Id.Equals(this.Id) 
                 select a.Attribute; 
      IQueryable<Attribute> otherAssocAttributes = from a in dbContext.PageAttributes 
                 where a.Page.Id.Equals(other.Id) 
                 select a.Attribute; 
      IQueryable<Attribute> interSection = thisAssocAttributes.Intersect(otherAssocAttributes); 

      return interSection.ToList().Count; 
      } 
     } 

यह बदसूरत है, लेकिन यह काम करता है।

public class Page 
{ 
    public List<Attribute> AssociatedAttributes 
    { 
     get 
     { 
      return new List<Attribute>() { 
       new Attribute { Value = "a" }, 
       new Attribute { Value = "b" }, 
       new Attribute { Value = "c" }, 
      }; 
     } 
    } 
} 

यहाँ AssociatedAttributes संपत्ति एक अलग सूची हर बार AssociatedAttributes कहा जाता है लौटा रहा है:

उत्तर

8

Page के निम्नलिखित कार्यान्वयन पर विचार करें। इसके अतिरिक्त, सूची में वास्तविक आइटम प्रत्येक बार संपत्ति कहलाते समय बनाए जाते हैं, यह केवल उसी सटीक Attribute ऑब्जेक्ट्स के संदर्भों को वापस नहीं कर रहा है। चूंकि Attribute (मुझे लगता है) Equals या GetHashCode ओवरराइड नहीं करता है, तो यह डिफ़ॉल्ट object कार्यान्वयन का उपयोग करेगा, जो वस्तुओं को बराबर मानता है और केवल तभी यदि वे एक ही ऑब्जेक्ट का संदर्भ दे रहे हैं। चूंकि आपकी दो सूचियों में ऑब्जेक्ट्स एक ही ऑब्जेक्ट का संदर्भ नहीं दे रहे हैं, उनमें से कोई भी एक दूसरे के बराबर नहीं है, भले ही उनके पास आंतरिक रूप से समान मूल्य हो।

तथ्य यह है कि Attribute लागू IComparable असंभव है। एक ही वास्तविक वस्तुओं के लिए

  1. संदर्भ बल्कि संपत्ति गेटर में नई वस्तुओं के निर्माण की तुलना में, वापसी:

    कई संभावित चीजें हैं जो व्यवहार बदलने के लिए किया जा सकता है कर रहे हैं। इसका अर्थ यह होगा कि संपत्ति के लिए निजी बैकिंग फ़ील्ड, ऑब्जेक्ट्स का निर्माण करना, और फिर उसी सूची में संदर्भ वापस करना होगा।

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

  3. IEqualityComparer<Attribute> लागू करने वाली एक नई वस्तु बनाएं। यह Attribute से बाहर एक वस्तु होगी जो जानता है कि Equals और GetHashCode ऑब्जेक्ट के कार्यान्वयन के अलावा कुछ अन्य चीज़ों के आधार पर समानता के लिए उनकी तुलना कैसे करें। ऐसे प्रकार का उदाहरण Intersect और Distinct पर प्रदान करें। (उनमें से प्रत्येक के पास कस्टम समानता तुलनाकर्ताओं के लिए ओवरलोड हैं।)

+0

हम्म, लेकिन मुझे पहले से मौजूद विशेषता वस्तुओं के वास्तविक संदर्भों की आवश्यकता है। मैं सिर्फ नए उत्पन्न नहीं कर सकता। यह छेड़छाड़ की गिनती पाने के उद्देश्य के लिए काम कर सकता है, लेकिन यह और भी काम नहीं करेगा कि वे नव निर्मित वस्तुओं हैं। मैंने परीक्षण के रूप में केवल पृष्ठ के छेड़छाड़ के रूप में यह देखने के लिए किया कि क्या मैं सही चीजों को कोड कर रहा हूं। – cray1

+0

@ user1911333 मैं यह नहीं कह रहा हूं कि आपको यह करना चाहिए, मैं कह रहा हूं कि मुझे लगता है कि आप पहले से ही यह कर रहे हैं (या इसी तरह के प्रभाव के साथ कुछ) आपके मनाए गए व्यवहार के लिए एक स्पष्टीकरण के रूप में। यदि आपने [मेरे प्रश्न] का जवाब दिया है (http://stackoverflow.com/questions/18365587/can-someone-explain-linqs-intersect-properly-to-me-i-dont-understand-why-this#comment26965710_18365587) कैसे संपत्ति लागू की गई है, मुझे अनुमान लगाने की आवश्यकता नहीं हो सकती है। मैं आपका कोड नहीं कह रहा हूं * मुझे इस तरह दिखना चाहिए; वास्तव में यह शायद नहीं होना चाहिए। अगर ऐसा होता है, तो यह काफी ... असामान्य होगा। – Servy

+0

अब जब आपने कार्यान्वयन जोड़ा है तो मैं ठोस रूप से कह सकता हूं कि आप वास्तव में गेटटर के भीतर नए ऑब्जेक्ट उदाहरण बना रहे हैं, और यह आपकी समस्या है। विकल्प 1 या 3 आपके लिए सबसे अच्छी शर्त है। एक ओआरएम ऑब्जेक्ट संभवतः उत्परिवर्तनीय है, और आमतौर पर 'समान' या 'गेटहाशकोड' विधियों को ओवरराइड करने की अपेक्षा नहीं की जाएगी। – Servy

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