2009-05-06 12 views
28

मैं एक कस्टम कॉन्फ़िगरेशन एलिमेंट कोलेक्शन लिख रहा हूं कस्टम कॉन्फ़िगरेशन हैंडलर सी # .NET 3.5 में और मैं जेन्यूमेरेटर को जेनेरिक आईनेमेरेटर के रूप में बेनकाब करना चाहता हूं।एक जेनेम्युलेटर को जेनेरिक आईनेमेरेटर में बदलने का सबसे अच्छा तरीका क्या है?

इसे प्राप्त करने का सबसे अच्छा तरीका क्या होगा?

मैं वर्तमान में कोड का उपयोग कर रहा:

 
public new IEnumerator<GenericObject> GetEnumerator() 
{ 
    var list = new List(); 
    var baseEnum = base.GetEnumerator(); 
    while(baseEnum.MoveNext()) 
    { 
    var obj = baseEnum.Current as GenericObject; 
    if (obj != null) 
     list.Add(obj); 
    } 
    return list.GetEnumerator(); 
} 

चीयर्स

उत्तर

45

मैं वहाँ ढांचे में कुछ भी है पर विश्वास नहीं है, लेकिन आप आसानी लिख सकता है एक:

IEnumerator<T> Cast<T>(IEnumerator iterator) 
{ 
    while (iterator.MoveNext()) 
    { 
     yield return (T) iterator.Current; 
    } 
} 

LINQ से Enumerable.Cast<T> पर कॉल करना और फिर परिणाम पर GetEnumerator() पर कॉल करना प्रलोभन है - लेकिन यदि आपकी कक्षा पहले से ही IEnumerable<T> औरलागू करती हैएक वैल्यू टाइप है, जो नो-ऑप के रूप में कार्य करता है, इसलिए GetEnumerator() कॉल रिकर्स करता है और StackOverflowException फेंकता है। return foo.Cast<T>.GetEnumerator(); का उपयोग करना सुरक्षित है जब foo निश्चित रूप से अलग ऑब्जेक्ट (जो इस पर वापस प्रतिनिधि नहीं है) लेकिन अन्यथा, आप ऊपर दिए गए कोड का उपयोग कर शायद सबसे अच्छे हैं।

+7

क्या आप सिर्फ अंक से गणक को वापस नहीं कर सकते? इसे वापस करें। कैस्ट () .GetEnumerator(); – flq

+0

फ्रैंक: आप बिल्कुल सही हैं :) –

+0

धन्यवाद यह धन्यवाद। आपकी प्रतिक्रियाओं के लिए आप सभी को धन्यवाद। – zonkflut

3

IEnumerable<T> पहले से ही IEnumerable से निकला है इसलिए किसी भी रूपांतरण करने के लिए कोई ज़रूरत नहीं है। आप इसे आसानी से डाल सकते हैं ... वास्तव में यह निश्चित रूप से कोई फसल जरूरी नहीं है।

IEnumerable<T> enumerable = GetGenericFromSomewhere(); 
IEnumerable sadOldEnumerable = enumerable; 
return sadOldEnumerable.GetEnumerator(); 

इसका उल्टा जा रहे LINQ के साथ और अधिक कठिन नहीं है:

var fancyEnumerable = list.OfType<GenericObject>(); 
return fancyEnumerable.GetEnumerator(); 
+0

मेरे बुरा मेरी विधि परिभाषा – zonkflut

+2

आप IEnumerable और IEnumerator भ्रमित कर रहे हैं करने के लिए सामान्य हिस्सा याद किया। IENumerable IENumerable और IENumerator से प्राप्त होता है INumerator से निकला है।यह "IENumerable theEnumerator" कहने के लिए बहुत अधिक समझ में नहीं आता है क्योंकि एक गणना करने वाला एक गणक नहीं है। –

+0

कास्टिंग मूल ऑब्जेक्ट में काम नहीं करता है संग्रह संग्रह को ArrayList में संग्रहीत किया जाता है। – zonkflut

0

आप OfType<T> और Cast<T> का उपयोग कर सकते हैं।

public static IEnumerable Digits() 
{ 
    return new[]{1, 15, 68, 1235, 12390, 1239}; 
} 

var enumerable = Digits().OfType<int>(); 
foreach (var item in enumerable) 
    // var is here an int. Without the OfType<int(), it would be an object 
    Console.WriteLine(i); 

प्राप्त करने के लिए एक IEnumerator<T> के बजाय एक IEnumerable<T> तुम सिर्फ GetEnumerator()

var enumerator = Digits().OfType<int>().GetEnumerator(); 
0

यह मेरे लिए काम करता लिए एक कॉल कर सकते हैं।

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator(); 
0

मैं उसी स्टैक ओवरफ़्लो समस्या में भाग रहा था, जिसमें कुछ टिप्पणियां दी गई हैं। मेरे मामले में यह इस तथ्य के कारण था कि GetEnumerator कॉल को आधार पर होना आवश्यक था। GetEnumerator अन्यथा आप अपने स्वयं के GetEnumerator redefinition के भीतर लूप करते हैं।

यह वह कोड है जो स्टैक ओवरफ़्लो थ्रोइंग था। foreach बयान के उपयोग एक ही GetEnumerator समारोह मैं अधिभार के लिए कोशिश कर रहा हूँ कहते हैं:

public new IEnumerator<T> GetEnumerator() 
{ 
    foreach (T type in this) 
    { 
     yield return type; 
    } 
} 

मैं मूल पोस्ट का एक सरलीकृत संस्करण के साथ समाप्त कर दिया के रूप में आप एक सूची धारक का उपयोग करने की जरूरत नहीं है।

public class ElementCollection<T> : ConfigurationElementCollection, IList<T> 
    ... 
    public new IEnumerator<T> GetEnumerator() 
    { 
     var baseEnum = base.GetEnumerator(); 
     while (baseEnum.MoveNext()) 
     { 
      yield return baseEnum.Current as T; 
     } 
    } 
    ... 
}