2012-11-16 15 views
55

में संघ बनाम कंसट मेरे पास Union और Concat पर एक प्रश्न है। मुझे लगता है कि List<T> के मामले में दोनों ही व्यवहार कर रहे हैं।लिंक

var a1 = (new[] { 1, 2 }).Union(new[] { 1, 2 });    // O/P : 1 2 
var a2 = (new[] { 1, 2 }).Concat(new[] { 1, 2 });   // O/P : 1 2 1 2 

var a3 = (new[] { "1", "2" }).Union(new[] { "1", "2" });  // O/P : "1" "2" 
var a4 = (new[] { "1", "2" }).Concat(new[] { "1", "2" }); // O/P : "1" "2" "1" "2" 

ऊपर परिणाम उम्मीद कर रहे हैं,

लेकिन List<T> के मामले में मैं एक ही परिणाम हो रही है।

class X 
{ 
    public int ID { get; set; } 
} 

class X1 : X 
{ 
    public int ID1 { get; set; } 
} 

class X2 : X 
{ 
    public int ID2 { get; set; } 
} 

var lstX1 = new List<X1> { new X1 { ID = 10, ID1 = 10 }, new X1 { ID = 10, ID1 = 10 } }; 
var lstX2 = new List<X2> { new X2 { ID = 10, ID2 = 10 }, new X2 { ID = 10, ID2 = 10 } }; 

var a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>());  // O/P : a5.Count() = 4 
var a6 = lstX1.Cast<X>().Concat(lstX2.Cast<X>()); // O/P : a6.Count() = 4 

लेकिन दोनों List<T> की बैठाना ही व्यवहार कर रहे हैं।

कोई सुझाव कृपया?

+1

आप इन दो विधियों के बीच अंतर पता है, यही कारण है कि परिणाम आश्चर्य आप करता है? यह विधियों की कार्यक्षमता का सीधा परिणाम है। –

+0

@ कोनराड रुडॉल्फ, मेरा मतलब है सूची की सूची है मैं किसी भी 'संघ'/'कंसट' का उपयोग कर सकता हूं। क्योंकि दोनों एक ही व्यवहार कर रहे हैं। –

+0

नहीं, जाहिर है नहीं।वे वही व्यवहार नहीं करते हैं, जैसा कि आपका पहला उदाहरण दिखाता है। –

उत्तर

68

यूनियन Distinct मान देता है। डिफ़ॉल्ट रूप से यह वस्तुओं के संदर्भों की तुलना करेगा। आपके आइटम में अलग-अलग संदर्भ हैं, इस प्रकार वे सभी अलग-अलग मानते हैं। जब आप आधार प्रकार X पर डाले जाते हैं, तो संदर्भ नहीं बदला जाता है।

आप को पार कर जाएगी तो Equals और GetHashCode (अलग आइटम का चयन करने के लिए इस्तेमाल किया), तो आइटम संदर्भ से तुलना नहीं की जाएगी:

class X 
{ 
    public int ID { get; set; } 

    public override bool Equals(object obj) 
    { 
     X x = obj as X; 
     if (x == null) 
      return false; 
     return x.ID == ID; 
    } 

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

लेकिन सभी अपने आइटम ID का मान अलग है। तो सभी वस्तुओं को अभी भी अलग माना जाता है। क्योंकि पूर्णांक मूल्य प्रकार के होते हैं और वे मूल्य से तुलना की जाती है

var lstX1 = new List<X1> { new X1 { ID = 1, ID1 = 10 }, 
          new X1 { ID = 10, ID1 = 100 } }; 
var lstX2 = new List<X2> { new X2 { ID = 1, ID2 = 20 }, // ID changed here 
          new X2 { ID = 20, ID2 = 200 } }; 

var a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>()); // 3 distinct items 
var a6 = lstX1.Cast<X>().Concat(lstX2.Cast<X>()); // 4 

आपका आरंभिक नमूना काम करता है,: आप एक ही ID साथ कई मदों प्रदान करेगा तो आप Union और Concat के बीच अंतर देखेंगे।

+2

भले ही यह संदर्भों की तुलना नहीं कर रहा था, लेकिन उदा। आईडी के भीतर, आईडी अभी भी चार आइटम होंगे क्योंकि आईडी अलग हैं। – Rawling

+0

@ रावलिंग सहमत हैं, यह भी सच है –

+0

@ सवाना नोप, वे नहीं हैं। मुझे लगता है कि आपने दूसरे संग्रह में पहले आइटम की आईडी नहीं बदली है, जैसा कि मैंने –

29

Concat सचमुच दूसरे अनुक्रम से वस्तुओं के बाद पहले क्रम से आइटम लौटाता है। यदि आप दो 2-आइटम अनुक्रमों पर Concat का उपयोग करते हैं, तो आपको हमेशा 4-आइटम अनुक्रम प्राप्त होगा।

Union अनिवार्य रूप से ConcatDistinct है।

अपने पहले दो मामलों में, आप 2-आइटम अनुक्रमों के साथ समाप्त होते हैं क्योंकि, उनके बीच, इनपुट वर्गों की प्रत्येक जोड़ी में दो अलग-अलग आइटम होते हैं।

अपने तीसरे मामले में, आप 4-आइटम अनुक्रम के साथ समाप्त होते हैं क्योंकि आपके दो इनपुट अनुक्रमों में सभी चार आइटम अलग-अलग हैं।

12

Union और ConcatUnion कस्टम IEqualityComparer<X> के बिना डुप्लिकेट का पता नहीं लगा सकता है। यह सिर्फ यह देख रहा है कि दोनों एक ही संदर्भ हैं।

public class XComparer: IEqualityComparer<X> 
{ 
    public bool Equals(X x1, X x2) 
    { 
     if (object.ReferenceEquals(x1, x2)) 
      return true; 
     if (x1 == null || x2 == null) 
      return false; 
     return x1.ID.Equals(x2.ID); 
    } 

    public int GetHashCode(X x) 
    { 
     return x.ID.GetHashCode(); 
    } 
} 

अब आप यह Union के अधिभार में उपयोग कर सकते हैं:

var comparer = new XComparer(); 
a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>(), new XComparer());