Güncelleme 7/17/2012: Görünüşe göre C # 5.0'dan itibaren foreach
, aşağıda açıklanan davranış değiştirildi ve " iç içe lambda ifadesinde yineleme değişkeninin kullanımı foreach
artık beklenmedik sonuçlar üretmiyor . " Bu yanıt C # ≥ 5.0 için geçerli değil .
@ John Skeet ve foreach anahtar kelimesini tercih eden herkes.
5.0'dan önceki C #'da "foreach" ile ilgili sorun, " anlama için" eşdeğerinin diğer dillerde nasıl çalıştığı ve nasıl çalışacağını beklediğim ile tutarsız olmasıdır (kişisel görüş burada sadece diğerleri tarafından belirtildiği için belirtilmiştir. okunabilirlik ile ilgili görüş). " Değiştirilmiş kapanışa erişim " ve " Zararlı sayılan döngü değişkeninin kapatılması " ile ilgili tüm soruları görün . Bu sadece "zararlı" çünkü "foreach" C # uygulanan yolu.
@Fredrik Kalseth'in cevabındaki işlevsel olarak eşdeğer uzatma yöntemini kullanarak aşağıdaki örnekleri alın.
public static class Enumerables
{
public static void ForEach<T>(this IEnumerable<T> @this, Action<T> action)
{
foreach (T item in @this)
{
action(item);
}
}
}
Aşırı tartışılmış örnek için özür dilerim. Sadece Gözlemlenebilir'i kullanıyorum çünkü böyle bir şey yapmak tamamen zor değil. Açıkçası bu gözlemlenebilir yaratmanın daha iyi yolları var, sadece bir noktaya göstermeye çalışıyorum. Tipik olarak gözlemlenebilir öğeye abone olunan kod, eşzamansız olarak ve potansiyel olarak başka bir iş parçacığında yürütülür. "Foreach" kullanılıyorsa, bu çok garip ve potansiyel olarak deterministik olmayan sonuçlar doğurabilir.
"ForEach" uzantısı yöntemini kullanarak aşağıdaki test geçer:
[Test]
public void ForEachExtensionWin()
{
//Yes, I know there is an Observable.Range.
var values = Enumerable.Range(0, 10);
var observable = Observable.Create<Func<int>>(source =>
{
values.ForEach(value =>
source.OnNext(() => value));
source.OnCompleted();
return () => { };
});
//Simulate subscribing and evaluating Funcs
var evaluatedObservable = observable.ToEnumerable().Select(func => func()).ToList();
//Win
Assert.That(evaluatedObservable,
Is.EquivalentTo(values.ToList()));
}
Aşağıdakiler hatayla başarısız olur:
Beklenen: <0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ile eşdeğer> Ama şuydu: <9, 9, 9, 9, 9, 9, 9, 9, 9, 9>
[Test]
public void ForEachKeywordFail()
{
//Yes, I know there is an Observable.Range.
var values = Enumerable.Range(0, 10);
var observable = Observable.Create<Func<int>>(source =>
{
foreach (var value in values)
{
//If you have resharper, notice the warning
source.OnNext(() => value);
}
source.OnCompleted();
return () => { };
});
//Simulate subscribing and evaluating Funcs
var evaluatedObservable = observable.ToEnumerable().Select(func => func()).ToList();
//Fail
Assert.That(evaluatedObservable,
Is.EquivalentTo(values.ToList()));
}
ForEach()
.