2011-09-05 14 views
48

C# 'da IEnumerator s kullanımını nasıl (ama neden değil) hatırlamakta sorun yaşıyorum. Yeni başlayanlara her şeyi açıklayan harika belgeleriyle Java'ya alışkınım. Öyleyse lütfen, benimle birlikte ol.Basit IEnumerator kullanımı (örneğin)

Bu forumlardaki diğer cevaplardan öğrenmeyi hiç bir işe yaramaya çalıştım. Daha önce sorulmuş olan genel bir soru sormak yerine, benim için bazı şeyleri açıklığa kavuşturacak belirli bir örneğim var.

Bir IEnumerable<String> nesnesinin geçirilmesi gereken bir yönteme sahibim. Tüm yöntemin yapması gereken, roxxors harflerini yineleyicideki her String sonuna bağlamanızdır. Sonra bu yeni yineleyiciyi (tabii ki IEnumerable nesnesinin olduğu gibi bırakılır) döndürür.

Bunun için nasıl giderim? Buradaki cevap, elbette bana ek olarak, bu nesnelerle ilgili temel sorulara da yardımcı olacaktır.

private IEnumerable<string> DoWork(IEnumerable<string> data) 
{ 
    List<string> newData = new List<string>(); 
    foreach(string item in data) 
    { 
     newData.Add(item + "roxxors"); 
    } 
    return newData; 
} 

Basit şeyler :)

cevap

78

IEnumerator. Uzunluğun zorunlu olarak önceden bilinemediği (hatta olsa bile) listelerin değerlerini almak için kullanılırlar. Bu kelime enumerate'dan gelir ve "tek tek saymak ya da isimlendirmek" anlamına gelir.

IEnumerator ve IEnumerator<T>GetEnumerator() ile .NET (ikinci iki sağlayan) her IEnumerable ve IEnumerable<T> arayüzleri sağlanır. Bu önemlidir, çünkü foreach deyimi, bu arabirim yöntemleri aracılığıyla numaralandırıcılar ile doğrudan çalışmak üzere tasarlanmıştır. Örneğin bu şekilde

:

IEnumerator enumerator = enumerable.GetEnumerator(); 

while (enumerator.MoveNext()) 
{ 
    object item = enumerator.Current; 
    // Perform logic on the item 
} 

Oldu:

foreach(object item in enumerable) 
{ 
    // Perform logic on the item 
} 

özel senaryoya gelince, hemen hemen .NET tüm koleksiyonları IEnumerable uygulamak.

public IEnumerator Enumerate(IEnumerable enumerable) 
{ 
    // List implements IEnumerable, but could be any collection. 
    List<string> list = new List<string>(); 

    foreach(string value in enumerable) 
    { 
     list.Add(value + "roxxors"); 
    } 
    return list.GetEnumerator(); 
} 
+0

Sıfırla() foreach tarafından çağrılmıyor. COM etkileşimi içindir ve tüm sayımcıları desteklemez (aslında çoğu numaralayıcı * bunu desteklemez). –

+0

Numaratörler salt okunur, doğru mu? Değişikliklerimi içeren bir numaralayıcı türünü böyle bir kalıp kullanarak nasıl iade edebilirim? – BlackVegetable

+0

@Martinho Haklısınız. –

5

ben böyle bir şey yapmak istiyorum.

örn.

IEnumerable<string> myMethod(IEnumerable<string> sequence) 
{ 
    foreach(string item in sequence) 
    { 
     yield return item + "roxxors"; 
    } 
} 
+0

burada Devamı Bu benim ilk düşünce oldu. Ancak, etkileşimde bulunduğum diğer yöntemler, IEnumerable türünü veya somesuch'u döndürmemi gerektirir. Cevabınız için teşekkürler! – BlackVegetable

+0

@BlackVegetable: 'List ' bir IEnumerable 'dir. Ama evet, bunu yapmak için daha iyi yollar vardır ('verim'). –

+1

Bir listeyi IEnumerable olarak bildirilen bir yöntemle döndürmemeyi denemeniz gerektiğini hatırlıyorum. Bunun nedeni, insanların "aldatma" yapabilmeleri ve aslında bir listesini görebilmeleri ve bununla ilgili bir şeyler yapmaya başlayabilmeleridir. Liste (ve gerçekten de tüm IEnumerables) üzerinde çağrılmalı ve geri döndürülmesi gerektiğini düşündüğüm bir AsEnumerable() yöntemi var. – Chris

8

i C# sonra doğru anlamak yield return derleyici sihirli sen bence gereken tek şey:

+0

Bu durumda, bu durumda, her çalıştırıldığında tek bir (değiştirilmiş) String'i döndürür. Yoksa bir çeşit IEnumerable Nesne mi döndürecek? – BlackVegetable

+0

@BlackVegetable Evet, her seferinde bir dize oluşturacak bir 'IEnumerable 'nesnesi döndürecektir' MoveNext' üzerinde çağrılır (ya doğrudan ya da dolaylı olarak foreach ile) –

+0

Evet, sözdizimsel şekerdir, derleyiciye bunu söylemesi söyler bir yineleyici bloğu içine. Buraya bakın http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx –

12
public IEnumerable<string> Appender(IEnumerable<string> strings) 
{ 
    List<string> myList = new List<string>(); 
    foreach(string str in strings) 
    { 
     myList.Add(str + "roxxors"); 
    } 
    return myList; 
} 

veya yield construct kullanılarak

public IEnumerable<string> Appender(IEnumerable<string> strings) 
{ 
    foreach(string str in strings) 
    { 
     yield return str + "roxxors"; 
    } 
} 

, ya da sadece

var newCollection = strings.Select(str => str + "roxxors"); //(*) 

veya

var newCollection = from str in strings select str + "roxxors"; //(**) 
: Bu nedenle, aşağıdakileri yapabilirsiniz Bu iki sonuncusunun LINQ ve (**), (*) için sözdizimsel şeker olduğu

.

+0

LINQ ile ilginç desen. Bunu araştırmam gerekecek. (Hızlı) yardımınız için hepinize teşekkür ederim! – BlackVegetable

+0

Bir listeyi IEnumerable olarak bildirilen bir yöntemle göndermemeyi denemeniz gerektiğini hatırlıyorum. Bunun nedeni, insanların "aldatma" yapabilmeleri ve aslında bir listesini görebilmeleri ve bununla ilgili bir şeyler yapmaya başlayabilmeleridir. Liste (ve gerçekten de tüm IEnumerables) üzerinde çağrılmalı ve geri döndürülmesi gerektiğini düşündüğüm bir AsEnumerable() yöntemi var. Aksi halde verim ve özellikle linq yanıtları için en iyi cevap. :) – Chris

+0

C# içinde önemli miktarda geliştirme yapmayı planlıyorsanız, LINQ içinde biraz zaman ayırmak isteyeceksiniz - bu size çok zaman kazandıracak ve kodunuzla ilgili daha iyi hissetmenizi sağlayacaktır :-) – Rune

4

Ayrıca LINQ en Seç Yöntemini kullanabilirsiniz:

var source = new[] { "Line 1", "Line 2" }; 

var result = source.Select(s => s + " roxxors"); 

Enumerable.Select Method