2012-07-04 15 views
11

बस सोच रहा है कि क्यों Enumerable.RangeIDisposable लागू करता है।क्यों समेकित। श्रेणी लागू IDISposable?

मुझे समझ में आता है कि क्यों IEnumerator<T> करता है, लेकिन IEnumerable<T> इसकी आवश्यकता नहीं है।


(मैं इस जबकि मेरी .Memoise() कार्यान्वयन, जो की तरह

if (enumerable is IDisposable) 
    ((IDisposable)enumerable).Dispose(); 
अपने "स्रोत समाप्त हो गया" विधि में

कि मैं curiousity से बाहर पर एक ब्रेकपाइंट रखा था बयान है के साथ खेल की खोज की, और एक परीक्षण द्वारा ट्रिगर किया गया था।)

+1

http://csharpindepth.com/articles/chapter6/iteratorblockimplementation.aspx –

उत्तर

7

Enumerable.Range अपने विधि शरीर में yield return का उपयोग करता है। yield return बयान, संकलक के जादू के तहत, इस तरह एक गुमनाम प्रकार है कि IDisposable लागू करता है पैदा करता है:

[CompilerGenerated] 
private sealed class <GetNumbers>d__0 
    : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable 
{ 
    //the implementation 
    //note the interface is implemented explicitly 
    void IDisposable.Dispose() { } 
} 
तो

:

static IEnumerable<int> GetNumbers() 
{ 
    for (int i = 1; i < 10; i += 2) 
    { 
     yield return i; 
    } 
} 

संकलित किये जाने के बाद, वहाँ इस तरह एक गुमनाम नेस्टेड वर्ग है परिणाम is एक IDisposable। इस उदाहरण में, Dispose विधि खाली छोड़ देता है। मुझे लगता है कि कारण यह है कि निपटान करने की जरूरत नहीं है। यदि आप yield return एक प्रकार है जिसमें अप्रबंधित संसाधन हैं, तो आपको एक अलग संकलन परिणाम मिल सकता है। (इसके बारे में सुनिश्चित नहीं)

+0

कंपाइलर एक ही कक्षा के साथ IENumerable और IENumerator दोनों लागू करता है? दिलचस्प। मुझे उन कार्यों के बारे में सोचना होगा। – Fowl

+0

ओह, अब मैं इसे देखता हूं। यह पता लगाने के लिए अपनी राज्य मशीन का उपयोग करता है कि क्या GetEnumerator को कई बार बुलाया गया है और यदि यह नहीं है तो खुद को लौटाता है। – Fowl

+0

यह समझ में आता है, लेकिन फैक्ट्री विधि होने से एक प्रकार वापस आ जाता है जो 'आईडीस्पोजेबल' लागू करता है जब फैक्ट्री का रिटर्न प्रकार एंटी-पैटर्न नहीं लगता है। 'उपज रिटर्न' के माध्यम से उत्पादित कंपाइलर-जेनरेटेड इटरेटर्स ऐसे प्रकार प्रतीत होते हैं जहां निपटान के बिना त्याग वास्तव में हानिकारक होगा, बशर्ते 'GetEnumerator() 'कभी नहीं कहा गया है, लेकिन एक बार' GetEnumerator()' कहा जाता है, आमतौर पर निपटान आवश्यक है । संयोग से, 'GetEnumerable() 'के बाद एक पुनरावर्तक पर' निपटान 'को कॉल करने के लिए कम से कम एक बार पहली बार गणनाकर्ता को अमान्य कर दिया जाएगा। – supercat

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