IList वैरिएबल में आइटम की एक श्रेणी कैसे जोड़ें


81

के लिए कोई AddRange()विधि नहीं है IList<T>

मैं IList<T>बिना आइटम के माध्यम से पुनरावृत्ति और Add()विधि का उपयोग करके वस्तुओं की सूची कैसे जोड़ सकता हूं ?

जवाबों:


66

AddRangeList<T>इंटरफ़ेस पर नहीं, पर परिभाषित किया गया है।

आप पहुँच प्राप्त करने के लिए List<T>इसके बजाय चर की घोषणा कर सकते हैं IList<T>या इसे डाल List<T>सकते हैं AddRange

((List<myType>)myIList).AddRange(anotherList);

इस के रूप में एक, अच्छा अभ्यास (नीचे टिप्पणी देखें) नहीं है IList<T>हो सकता है नहीं एक हो List<T>, लेकिन कुछ अन्य प्रकार है कि इंटरफ़ेस कार्यान्वित किया है और बहुत एक नहीं होती AddRangeइस तरह के एक मामले में, आप केवल जब अपने कोड एक फेंकता पता चलेगा - विधि रनटाइम पर अपवाद।

इसलिए, जब तक आप कुछ के लिए नहीं जानते कि प्रकार वास्तव में है जिसे List<T>आपको उपयोग करने का प्रयास नहीं करना चाहिए AddRange

ऐसा करने का एक तरीका ऑपरेटर के रूप में या (सी # 7 के बाद से) के प्रकार का परीक्षण करके है ।

if(myIList is List<T>)
{
   // can cast and AddRange
}
else
{
   // iterate with Add
}

2
@ mohsen.d - यदि प्रकार उत्पन्न होता है, तो आप जनरेट किए गए कोड को बदलना नहीं चाहते हैं (क्योंकि यह ओवरराइट किया जा सकता है)। या तो डाली या LINQ का उपयोग करें Concat, जैसा कि @Self_T-0_Programmer ने उत्तर दिया
ओड

2
@ mohsen.d - यदि यह आपका कोड है, List<T>तो आप इस प्रकार के रूप में भी घोषणा कर सकते हैं (या, यदि यह आपके लिए अच्छा विकल्प नहीं है, तो उस स्थान पर कास्ट करें जहां आपको AddRangeइसे स्थानीय रखने की आवश्यकता है - यह बहुत कम लागत वाला ऑपरेशन है ) है।
ऊद

53
नहीं नहीं नहीं। इसका कारण यह है कि IList <T> के साथ शुरू करना है क्योंकि यह सूची <T> कार्यान्वयन के अलावा कुछ और हो सकता है। यदि आपको वास्तव में एक AddRange विधि की आवश्यकता है, तो एक विस्तार विधि लिखें जैसा कि BlackjacketMack द्वारा दिखाया गया है।
डेरेक ग्रीर

6
पता नहीं क्यों इसने इतने उथल-पुथल प्राप्त किए क्योंकि यह स्पष्ट रूप से कुछ फेंक देगा जैसे InvalidCastExceptionकि List<T>(उदाहरण के लिए, सरणी) के अलावा किसी और चीज़ पर उपयोग किया जाता है ।
बशीस

3
लेकिन, कास्टिंग एक अच्छा विचार नहीं है। यह ओवरहेड प्रदर्शन कर सकता है।
गुल इरशाद

79

यदि आप सूची के लिए c # स्रोत कोड को देखते हैं , तो मुझे लगता है कि List.AddRange () में अनुकूलन है जो एक साधारण लूप को संबोधित नहीं करता है। इसलिए, एक विस्तार विधि को बस यह देखने के लिए जांचना चाहिए कि क्या आइलिस्ट एक सूची है, और यदि ऐसा है तो अपने मूल AddRange () का उपयोग करें।

स्रोत कोड के आस-पास पोज़ करते हुए आप देखते हैं कि .NET लोग अपने लाइनक एक्सटेंशन में इसी तरह की चीजों को करते हैं जैसे .ToList () (यदि यह एक सूची है, तो इसे कास्ट करें ... अन्यथा इसे बनाएं)।

public static class IListExtension
{
    public static void AddRange<T>(this IList<T> list, IEnumerable<T> items)
    {
        if (list == null) throw new ArgumentNullException(nameof(list));
        if (items == null) throw new ArgumentNullException(nameof(items));

        if (list is List<T> asList)
        {
            asList.AddRange(items);
        }
        else
        {
            foreach (var item in items)
            {
                list.Add(item);
            }
        }
    }
}

6
देखने का अनुकूलन बिंदु से, आप वास्तव में कास्ट कर रहे हैं listकरने के लिए List<T>दो बार यहां। जिनमें से एक को asकीवर्ड से दूर रखा जा सकता है ।
बशीस

अच्छी कॉल @ बशी। मैं हमेशा हमारे नए संस्करण के एक डबल कास्ट बनाम जीसी सफाई की लागत पर आगे और पीछे जाता हूं। लेकिन हम वास्तव में var listCasted = list को List <T> के रूप में कर सकते हैं; if (listCasted! = null) ... शायद c # 6 डिक्लेरेशन एक्सप्रेशन इस पैटर्न को बदल देंगे: if (myVar.As (out myVarCasted)) myVarCasted ...)
BlackjacketMack

क्या आप बताए गए अनुकूलन के साथ कोड को अपडेट कर सकते हैं? मैं अभी तक नवीनतम सुविधाओं में उतना धाराप्रवाह नहीं हूं। @ ब्लेकजैकेटमेक

2
@zuckerthoben - मैं सिर्फ दोनों दृष्टिकोणों का उपयोग करके एक मिलियन पुनरावृत्तियों का पुनरावलोकन करता था और प्रदर्शन में कोई अंतर नहीं था। इसलिए मैं इसे एक अनुकूलन नहीं कहूंगा ... इसके अलावा, यह कोड की एक पंक्ति जोड़ता है (लेकिन एक कास्टिंग को कम करता है)। किसी भी तरह, मैं शायद 'इन दिनों' के रूप में उपयोग करूँगा: सूची सूची = सूची के रूप में सूची <टी>; if (listCasted! = null) {listCasted.AddRange (आइटम);}। उत्तर IMHO अद्यतन करने के लायक नहीं है, लेकिन एक वाक्यात्मक विकल्प के रूप में पेश करने के लिए अच्छा है।
ब्लैकजैकेटमैक

2
अब आप कर सकते हैंif (list is List<T> castedList) { castedList.AddRange(items); }
एंड्रे मंटस

23

आप ऐसा कुछ कर सकते हैं:

IList<string> oIList1 = new List<string>{"1","2","3"};
IList<string> oIList2 = new List<string>{"4","5","6"};
IList<string> oIList3 = oIList1.Concat(oIList2).ToList();

तो, मूल रूप से आप Concat()एक्सटेंशन का उपयोग करेंगे और ToList()जैसी कार्यक्षमता प्राप्त करेंगे AddRange()

स्रोत


1
आपके दृष्टिकोण के साथ समस्या यह Enumerable.Concatहै System.Linq.Enumerableकि इस पद्धति द्वारा कार्यान्वित किया जाता है और IEnumerable<TSource>इसलिए मुझे विश्वास है कि इसे वापस नहीं डाला जाना चाहिए IList<TSource>- यह कार्यान्वयन विवरणों के कारण कुछ और वापस आ सकता है जो हमें स्रोत कोड की जांच के बिना नहीं पता है - हालांकि, इसकी कोई गारंटी नहीं है कि यह परिवर्तित नहीं होगा - इसलिए कई .NET संस्करणों का समर्थन करते समय विशेष ध्यान रखा जाना चाहिए।
jweyrich

8

आप इस तरह से एक एक्सटेंशन विधि भी लिख सकते हैं:

internal static class EnumerableHelpers
{
    public static void AddRange<T>(this IList<T> collection, IEnumerable<T> items)
    {
        foreach (var item in items)
        {
            collection.Add(item);
        }
    }
}

उपयोग:

        IList<int> collection = new int[10]; //Or any other IList
        var items = new[] {1, 4, 5, 6, 7};
        collection.AddRange(items);

जो अभी भी आइटम पर पुनरावृत्ति कर रहा है, लेकिन आपको हर बार कॉल करने पर इसे लिखने या डालने की ज़रूरत नहीं है।


2

LINQ का उपयोग कर एक और उत्तर, बशर्ते आप जो चीज़ जोड़ रहे हैं वह एक है List<T>या आप ToList()उस पर कॉल कर सकते हैं:

IEnumerable<string> toAdd = new string[] {"a", "b", "c"};
IList<string> target = new List<string>();

toAdd.ToList().ForEach(target.Add);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.