2009-12-21 10 views
7

निम्न कोड पर विचार करें, पहला यह दर्शाता है कि "क्लीनअप" निष्पादित होता है जब हम स्ट्रिंग के IENumerable पर फिर से समाप्त हो जाते हैं। दूसरा पास मुझे दुःख पैदा कर रहा है। मुझे अंत तक पहुंचने से पहले IENumerable को छोड़ने में सक्षम होना चाहिए, और उसके बाद साफ़ कोड निष्पादित करें। लेकिन यदि आप इसे चलाते हैं तो आप देखेंगे कि दूसरे पास में साफ सफाई कभी नहीं होती है।मैं अंत में पुन: प्रयास किए बिना एक आईन्यूमेरेटर को कैसे छोड़ सकता हूं?

इस तरह एक आईनेमरेबल को त्यागने का पसंदीदा तरीका क्या है?

static void Main(string[] args) 
{ 
    // first pass 
    foreach (String color in readColors()) 
     Console.WriteLine(color); 

    // second pass 
    IEnumerator<string> reader = readColors().GetEnumerator(); 
    if (reader.MoveNext()) 
    { 
     Console.WriteLine(reader.Current); 
     reader.Dispose(); 
    } 
} 
static IEnumerable<string> readColors() 
{ 
    string[] colors = { "red", "green", "blue" }; 
    for (int i = 0; i < colors.Length; i++) 
     yield return colors[i]; 

    Console.WriteLine("Cleanup goes here"); 
} 
+1

मैं कुछ याद आ रही हो सकता है, या अपने उदाहरण अति सरल है ... लेकिन क्या सफाई आप readColors में गणन के अंत में चलाने के लिए ened करते हैं? ऐसा लगता है कि जीसी चीजों को ठीक से संभालने में सक्षम होना चाहिए। –

+0

यदि आपके पास कस्टम संग्रह है, तो आप आईडीआईस्पोज़ेबल भी लागू कर सकते हैं?! – serhio

उत्तर

7

आप के साथ, एक try..finally में अपने इटरेटर विधि का मुख्य हिस्सा रखना होगा:

using (IEnumerator<string> reader = readColors().GetEnumerator()) { 
    reader.MoveNext(); 
    Console.WriteLine(reader.Current); 
} 

सफाई कोड के लिए मजबूर कर के रूप में आप पर अमल करने आप निम्न कर सकते है अंत में में सफाई कोड:

public IEnumerable<string> readColors() 
    { 
     try 
     { 
      string[] colors = { "red", "green", "blue" }; 
      for (int i = 0; i < colors.Length; i++) 
       yield return colors[i]; 
     } 
     finally 
     { 
      Console.WriteLine("Cleanup goes here"); 
     } 
    } 

याद रखें कि हुड के नीचे एक इटरेटर विधि बनाया जाना एक अलग वर्ग है, कि IEnumerable औरलागू करता है का कारण बनता है 210। आखिरकार ब्लॉक में अपना क्लीनअप डालने से, यह जेनरेट क्लास 'Dispose विधि में समाप्त होता है।

[संपादित करें: (के रूप में अन्य उत्तर में बताया) Dispose मैन्युअल बुलाने की अपने दृष्टिकोण पर एक using बयान पसंद करते हैं। मैं मान रहा था कि आपने चर्चा के तहत इस मुद्दे को हाइलाइट करने के लिए ऐसा किया होगा, लेकिन यह किसी भी तरह से इंगित करने योग्य है]

+0

@ ल्यूक: हाँ वह है। वह पंक्ति 'पाठक है। प्रदर्शन(); '। – jason

+0

यह सही जवाब है, एक बार ऐसा करने के बाद, आप अभी भी अधिक जटिल कोड की बजाय "foreach" का उपयोग करने के लिए अपनी दूसरी पंक्ति को सरल बना सकते हैं। बस करें: foreach (readColors() में स्ट्रिंग रंग) {Console.WriteLine (रंग); टूटना; } – StarPacker

4

यह त्यागने का एक तरीका है। कारण यह है कि आप नहीं देख रहे हैं

Cleanup goes here 

कंसोल पर मुद्रित क्योंकि पाश for (int i = 0; i < colors.Length; i++) कभी नहीं पूरा होने से चलाता है। निष्पादित करने के लिए क्लीनअप कोड को मजबूर करने के लिए नीचे देखें।

यहां एक और तरीका है। सी # में IDisposable ऑब्जेक्ट्स का उपयोग करने के लिए यह पसंदीदा पैटर्न है। इसे प्राथमिकता दी जाती है क्योंकि यह IEnumerator.Dispose का कारण बनता है, भले ही कोई अपवाद होता है।

static IEnumerable<string> readColors() { 
    string[] colors = { "red", "green", "blue" }; 
    try { 
     for (int i = 0; i < colors.Length; i++) { 
      yield return colors[i]; 
     } 
    } 
    finally { 
     Console.WriteLine("Cleanup goes here"); 
    } 
} 
+0

@Downvoter: एक कारण दें। – jason

+0

जब मैंने डाउनवोट दिया, तो जवाब की केवल कुछ पंक्तियां थीं जो अधिक समझ में नहीं आतीं। अब आपने स्पष्ट किया है, मैंने इसे हटा दिया है। –

+0

@ रोब लेविन: मैंने थोड़ी देर से पर्याप्त निष्पक्ष रूप से प्रस्तुत किया क्लिक किया। टिप्पणी करने के लिए वापस आने के लिए धन्यवाद। – jason

1

मुझे लगता है कि क्लीनअप करने का पसंदीदा तरीका IDisposable का उपयोग कर है। इस मामले में, एक विशिष्ट IEnumerator<string> के साथ अपने IEnumerable<string> को कार्यान्वित करने और सामान्य Dispose विधि का उपयोग करने से बेहतर है। foreach का उपयोग करते समय आपको मुफ्त के लिए निपटान मिलता है।

class MyEnumerator : IEnumerator<string> 
    { 
     // ... 
     #region IDisposable Members 

     public void Dispose() 
     { 
      // do your cleanup here 
      throw new NotImplementedException(); 
     } 

     #endregion 
     // ... 
    } 
+0

डाउनवोट क्यों? –

+1

आपको अपने आप को लागू करने की आवश्यकता नहीं है - जब तक आप अंततः ब्लॉक में क्लीनअप डालते हैं तब तक संकलक आपके लिए ऐसा करेगा। –

+0

आपका शायद सही है, और साधारण मामलों के लिए मुझे लगता है कि आपका उत्तर बेहतर है। –

0
try { 

    string[] colors = { "red", "green", "blue" }; 
    for (int i = 0; i < colors.Length; i++) { 
    if(condition == true) 
     break; 
    yield return colors[i]; 
    } 
} 
finally { 
    Console.WriteLine("Cleanup goes here"); 
} 
+0

@ ल्यूक: हाँ वह है। वह पंक्ति 'पाठक है। प्रदर्शन(); '। – jason

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

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