2010-06-22 12 views
7

मुझे आश्चर्य है कि एक्सटेंशन विधियों का उपयोग करके एक सामान्य सूची से सभी वस्तुओं को निकालना संभव है। इस कोड की तरह कुछ:विस्तार विधियों का उपयोग कर सी # में सूची <T> से किसी प्रकार के प्रकार की वस्तुओं को निकालें?

public static Remove<T>(this List<[any type]> list) 
{ 
    // some code to remove the objects of type T from the list 
} 

मैं निम्नलिखित कोड का उपयोग करके ऐसा कर सकते हैं:

public static Remove<T, K>(this List<K> list) 
{ 
    // some code to remove the objects of type T from the List<K> 
} 

लेकिन मैं सिर्फ प्रकार (टी) पर उपयोग करना चाहते हैं, द्वारा किसी भी प्रकार लालकृष्ण निर्दिष्ट करने के लिए आवश्यकता के बिना कर रही है कि उपयोगकर्ता द्वारा इस विस्तार विधि का उपयोग कर सकते हैं बस इस बारे में:

List<object> list = new List<object>(); 
list.Add(1); 
list.Add("text"); 

// remove all int type objects from the list 
list.Remove<int>(); 

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

सादर

उत्तर

7

सुनिश्चित नहीं हैं कि अगर यह काम करते हैं या नहीं होगा ... लेकिन यह लायक है एक शॉट (मैं दोहरी जांच करने के लिए संकलन नहीं कर सकते हैं):

public static void Remove<T>(this IList list) 
{ 
    if(list != null) 
    { 
     var toRemove = list.OfType<T>().ToList(); 

     foreach(var item in toRemove) 
      list.Remove(item); 
    } 
} 

या आप कुछ और भी अधिक सख्त जरूरत है (किसी ऑब्जेक्ट की बजाय जिसे टाइप किया जा सकता है), आप कोशिश कर सकते हैं:

public static void Remove<T>(this IList list) 
{ 
    if(list != null) 
    { 
     var toRemove = list.Where(i => typeof(i) == typeof(T)).ToList(); 

     foreach(var item in toRemove) 
      list.Remove(item); 
    } 
} 

सिद्धांत रूप में, आपको जाने के लिए अच्छा होना चाहिए। List<T> लागू IList जो IEnumerable लागू करता है। IList Remove() प्रदान करता है और IENumerable एक्सटेंशन विधि प्रदान करता है।

ध्यान रखें कि यह निश्चित रूप से संग्रह में प्रकारों के आधार पर अप्रत्याशित परिणाम उत्पन्न कर सकता है। मैं जॉन स्कीट से सहमत हूं ... यह सबसे निश्चित रूप से बदसूरत है।

+0

देखें, इसलिए हमें अब रिटर्न प्रकार प्रदान नहीं करना होगा; ओ) –

+0

ऑफ़ टाइप टाइप करने के लिए जा सकने वाले प्रत्येक ऑब्जेक्ट को वापस कर देगा। यह बहुत से तत्वों को हटा सकता है ... –

+0

यह दो tweaks के साथ काम करता है :) –

0

आपको क्या करने की कोशिश कर रहे हैं एक प्रकार पैरामीटर पर प्रकार निष्कर्ष काम है, लेकिन स्पष्ट रूप से अन्य निर्दिष्ट है। मुझे डर है सी # यह अनुमति नहीं देता है।

जस्टिन द्वारा दिए गए गैर-जेनेरिक IList का उपयोग करने वाला फ़ॉर्म काम करेगा क्योंकि इसमें केवल एक प्रकार पैरामीटर (निकालने के लिए तत्व का प्रकार) है। हालांकि यह बहुत बदसूरत है।

क्या यह वास्तव में आपको अक्सर इतना आवश्यक है कि आप दोनों प्रकार के तर्क निर्दिष्ट करने के बारे में परेशान हैं?

3

क्या आपको फ़िल्टर प्रकार को जेनेरिक के रूप में प्रदान करने की आवश्यकता है?

public static IEnumerable<T> Remove<T>(this IEnumerable<T> items, 
              Type removeThese) 
{ 
    return items.Where(i => !removeThese.IsInstanceOfType(i)); 
} 

// usage 
var newSet = mylist.Remove(typeof(int)); 
+0

अं के रूप में लागू किया जा सकता है, यह सिर्फ एक 'IEnumerable ' कि आइटम * के * नहीं के सभी का प्रतिनिधित्व करता है का उत्पादन करेगा निर्दिष्ट प्रकार यह सुनिश्चित नहीं है कि यह ओपी के मूल उद्देश्य के लिए कैसे काम करता है। –

+0

मुझे रिटर्न टाइप नहीं मिला, इसलिए मुझे लगता है कि वह इसे एक साथ ऑब्जेक्ट चेन करना चाहता था। यदि आप वापसी के बिना तत्व को हटाना चाहते हैं तो जस्टिन का जवाब –

1

मैं इसकी अनुशंसा नहीं करता, क्योंकि यह एक एपीआई जैसा लगता है जिसे समझना और बनाए रखना बहुत मुश्किल होगा।

कहा जा रहा है, निम्नलिखित काम करना चाहिए:

public static void Remove<T>(this IList list) 
{ 
    // Cycle through everything, comparing the types. 
    for (int index = list.Count; index >= 0; --index) 
    { 
     // Get the object. 
     object item = list[index]; 

     // If the item is null, continue. 
     if (item == null) continue; 

     // Remove the item if the types match. 
     if (typeof(T) == item.GetType()) list.RemoveAt(index); 
    } 
} 

नोट है कि आप केवल List<T> के लिए इसका उपयोग कर सकते हैं:

public static void Remove<T>(this IList list) 
{ 
    Type type = typeof(T); 
    var itemsToRemove = list.Cast<object>.Where(o => o.GetType() == type).ToList(); 
    foreach(var item in itemsToRemove) 
    { 
      list.Remove(item); 
    } 
} 
+0

क्यों 'ToList' को कॉल करें? – StriplingWarrior

+2

@StriplingWarrior: आपको LINQ क्वेरी का मूल्यांकन करने की आवश्यकता है, या एक तत्व को हटाने के बाद संभावित रूप से अपवाद फेंक देगा, क्योंकि आप अभी भी इसका मूल्यांकन कर रहे हैं क्योंकि आप संग्रह संपादित कर रहे हैं। –

+0

अच्छा जवाब। धन्यवाद। – StriplingWarrior

0

क्या तुम सच में क्या करना चाहते हैं तो जैसा कोई एक्सटेंशन विधि है , क्योंकि यह गैर-जेनेरिक IList इंटरफ़ेस लागू करता है। IList<T> इंटरफ़ेस गैर-जेनेरिक IList इंटरफ़ेस से प्राप्त होता है।

+0

पहले पैरामीटर से पहले एक एक्सटेंशन विधि को 'इस' कीवर्ड की आवश्यकता होती है। – StriplingWarrior

0

यहां एक और संस्करण है। यदि आप विधि को श्रृंखलाबद्ध करना चाहते हैं तो केवल तभी उपयोग किया जाता है।

public static List<TList> Remove<TList, TRemove>(this List<TList> list) 
{ 
    list.RemoveAll(item => item is TRemove); 
    return list; 
} 
-1

मैं निम्नलिखित कोड का उपयोग करके यह करने के लिए कामयाब रहे जस्टिन Niessner के greate जवाब देने के लिए धन्यवाद:

public static void Remove<T>(this IList list) 
{ 
    ArrayList deleteList = new ArrayList(); 

    foreach (var item in list) 
     if (item.GetType() == typeof(T)) 
      deleteList.Add(item); 

    for (int i = 0; i < deleteList.Count; i++) 
     list.Remove(deleteList[i]);   
} 
जस्टिन Niessner में

का जवाब वहाँ एक समस्या है। आप foreach ब्लॉक में एक enumarator आइटम को हटा नहीं सकते हैं।

0

मैं शायद की तरह कुछ करना होगा:

enumerable.Cast<object>().Where(o => !(o is T)) 

और तथ्य यह है कि गणनीय एक सूची है को छोड़ दें। (यहां कास्ट यह सुनिश्चित करने के लिए उपयोग किया जा रहा है कि जहां काम करता है, यदि आपके पास पहले से ही सामान्य जेनेरिक है तो आप इसे छोड़ सकते हैं)

0

सूची के माध्यम से पीछे की ओर कदम उठाएं और अवांछित प्रकार से मेल खाने वाले लोगों को हटा दें।

public static void RemoveAllOfType<T>(this IList list) 
{ 
    for(int index = list.Count - 1; index >= 0; index --) 
    { 
     if(list[index] is T) 
     { 
      list.RemoveAt(index); 
     } 
    } 
} 

आप हमेशा List<object> का उपयोग करने की आप एक छोटे से अधिक चीजों को आसान बनाने में कर सकते हैं जा रहे हैं।

public static void RemoveAllOfType<T>(this List<object> list) 
{ 
    list.RemoveAll(item => item is T); 
} 

हैप्पी कोडिंग!

0

सुनिश्चित नहीं हैं कि अगर ऐसा करेंगे

static class test 
    { 
     public static void RemAll<T>(this List<Object> self, T t) where T : Type 
     { 
      self.RemoveAll(x => x.GetType()==t); 
     } 
    } 

नीचे

static void Main(string[] args) 
     { 
      List<object> ll = new List<object>() { 1, 2, "abcd", "xyz", 22.3, 900, "junk" }; 
      ll.RemAll(typeof(int)); 
      ll.ForEach(x => Console.WriteLine(x)); 
     } 
संबंधित मुद्दे