2010-11-12 10 views
5

Özellikle aynı yöntemi birden çok kez zincirleme yaparken, linq yöntemlerini zincirlerken C# derleyicisinin ne yaptığını kafamın üzerine kaydırmaya çalışıyorum.C# derleyicisinin, linq yöntemlerini zincirleme ile nasıl anlaştığını anlama

Basit örnek: İki koşul temelinde, bir init dizisini filtrelemeye çalışıyorum. yapmak

en belirgin şey böyle bir şeydir:

IEnumerable<int> Method1(IEnumerable<int> input) 
{ 
    return input.Where(i => i % 3 == 0 && i % 5 == 0); 
} 

Ama ayrıca her tek koşulu ile, nerede yöntemleri zincirlemek olabilir:

IEnumerable<int> Method2(IEnumerable<int> input) 
{ 
    return input.Where(i => i % 3 == 0).Where(i => i % 5 == 0); 
} 

Ben vardı Reflektörde IL'ye bakın; o iki yöntem için tabii ki farklı, ancak daha da analiz an :) Ben öğrenmek istiyorum

de bilgime ötesindedir:
a) derleyici her defasında farklı olarak yaptıkları, ve neden.
b) bir performans sonuçları vardır (mikro-optimize çalışırken değildir;! Sadece merak) ilk

cevap

9

cevabı (a) ' kısa, ama aşağıda daha ayrıntılı olarak ele alacağız: derleyici aslında zincirleme yapmaz

- normal aracılığıyla, zamanında olur nesnelerin organizasyonu! İlk bakışta görülebilecek olandan çok daha az sihir var - Jon Skeet recently completed the "Where clause" step blog dizisinde, LINQ'un Nesneleri Yeniden Uygulaması. Bunu okumayı tavsiye ederim. o iki şey vardır yeni WhereEnumerable nesnesi döndürür, her zaman Where uzatma yöntemini çağırın - Bir önceki IEnumerable (eğer Where çağırdı biri) bir başvuru ve: Çok kısa açısından

, ne olur bu sağladığınız lambda.

Eğer (daha sonra aşağı kodunda bir foreach örneğin) bu WhereEnumerable üzerinde yineleme başlamak

, içten sadece o başvurulan etti IEnumerable bu konuda yineleme başlar.

"Bu foreach sadece bu yüzden etrafında dönen ve sizin dizideki bir sonraki element için soruyorum, benim dizideki bir sonraki elemana sordu". biz aslında dizi veya gerçek elemanların depolama çeşit köken, vurmak kadar tüm yol zinciri iner

.Her bir Numaralama, "Tamam, işte benim elementim" diyerek zincire geri dönerek, kendi özel mantığını da uygular. Bir Where için, elemanın ölçütleri geçip geçmediğini görmek için lambda'yı uygular. Eğer öyleyse, sonraki arayana devam etmesine izin verir. Başarısız olursa, bu noktada durur, başvurulan Numaralandırmaya döner ve bir sonraki öğeyi sorar.

Bu, herkesin MoveNext ifadesi yanlış olana kadar devam eder; yani, numaralandırma tamamlandı ve başka öğe yok demektir.

(b), hep arada fark var yanıtlamak için ama burada çok rahatsız kadar Önemsiz. Endişelenme :)

+0

Güzel cevap. Stackoverflow'ta bunun gibi daha fazla malzemeye ihtiyacımız var. –

1
  1. bir yineleyici kullanır, ikinci iki kullanır. Yani, ilk bir aşamada bir boru hattı kurar, ikincisi iki aşamayı içerecektir.

  2. İki yineleyici, bir birine düşük performans dezavantajına sahiptir.