2012-07-04 16 views
11

Sadece Enumerable.Range'un neden IDisposable uygulandığını merak ediyor.Enumerable.Range Uygulaması Neden Kullanılmaz?

Neden IEnumerator<T>'un neden olduğunu anlamıyorum, ancak IEnumerable<T> gerektirmiyor.


(Ben curiousity dışı bir kesme noktası koymuş onun "kaynak bitmiş" yönteminde

if (enumerable is IDisposable) 
    ((IDisposable)enumerable).Dispose(); 

gibi deyimi vardır benim .Memoise() uygulanması ile oynarken bu süre keşfetti ve bir test ile tetiklendi.)

+1

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

cevap

7

Enumerable.Range, kendi yöntem gövdesinde yield return kullanır. yield return deyimi böyle, derleyici sihirli altında IDisposable uygulayan bir anonim tür üretir: böylece

[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() { } 
} 

: derlenmiş sonra

, böyle bir anonim iç içe sınıf yoktur
static IEnumerable<int> GetNumbers() 
{ 
    for (int i = 1; i < 10; i += 2) 
    { 
     yield return i; 
    } 
} 

Sonuç a IDisposable. Bu örnekte, Dispose yöntemi boş bırakır. Bunun sebebi, bertaraf edilmek için hiçbir şeyin gerekmediği. Yönetilmeyen kaynaklar içeren bir tür yield return ise, farklı bir derleme sonucu alabilirsiniz. (Bu konuda emin değil)

+0

Derleyici aynı sınıfta hem IEnumerable hem de IEnumerator uygular? İlginç. Bu işleri düşünmek zorundayım. – Fowl

+0

Oh, şimdi görüyorum. GetEnumerator'ın birden çok kez çağrılıp çağrılmadığını tespit etmek için durum makinesini kullanır ve eğer değilse, geri döner. – Fowl

+0

Bu mantıklı, ancak bir fabrika yöntemine sahip olmak, fabrika dönüş tipi bir anti-desen görünmüyorsa, "IDisposable" uygulayan bir tür döndürür. "Getiri dönüşü" ile üretilen derleyici tarafından oluşturulan yineleyiciler, "GetEnumerator()" adlı hiçbir zaman çağrılmadıkça, elden çıkarma işleminden vazgeçmenin zararsız hale gelebileceği tipler olarak görünebilir, ancak bir kez GetEnumerator() 'a çağrıldığında, imha genel olarak gereklidir . Bu arada, GetEnumerable() 'dan sonra bir yineleyici üzerine 'Dispose' çağrılması en az bir kez çağrıldı, sadece ilk numaralayıcıyı geçersiz kılar. – supercat

İlgili konular