Svish Skrevet 9. januar 2009 Del Skrevet 9. januar 2009 (endret) Ble lei av å måtte kjøre IEnumerables.ToList() for å kunne bruke .ForEach(action). Så tenkte jeg kunne være lur å lage min egen vri: public static IEnumerable<TSource> ForEach<TSource>( this IEnumerable<TSource> source, Action<TSource> action) { foreach(TSource e in source) { action.Invoke(e); yield return e; } } Men... den fungerte ikke. Virker ikke som den blir kjørt en gang. Og jeg fatter ikke hvorfor. Testet den slik: var range = Enumerable.Range(1, 10).Select(ø => ø.ToString()); range.ForEach(ø => Console.WriteLine(ø)); Men ingenting skrives ut. Setter den til å breake på ForEach metoden, men det breakes ikke. Hvis jeg derimot setter retur typen til void og fjerner yield return e, slik: public static void ForEach<TSource>( this IEnumerable<TSource> source, Action<TSource> action) { foreach (TSource e in source) { action.Invoke(e); } } Da kjøres den som den skal, tallene skrives ut og den breaker hvis jeg setter breakpoint på ForEach moetoden. Hvorfor det? I don't get it... er det noe jeg har gått glipp av her? (Grunnen til yield return osv, var at jeg tenkte det kunne være kjekt å neste den etter en while for eksempel og så videre med noe annet, slik en kan gjøre med de fleste andre IEnumerable extension metodene.) Endret 9. januar 2009 av Svish Lenke til kommentar
BennyXNO Skrevet 9. januar 2009 Del Skrevet 9. januar 2009 Jeg gjorde ingen endringer i koden din! public static class RangeStatic { public static IEnumerable<TSource> ForEach<TSource>( this IEnumerable<TSource> source, Action<TSource> action) { foreach (TSource e in source) { action.Invoke(e); yield return e; } } } Jeg kjørte en test. [Test] public void Test() { var range = Enumerable.Range(1, 10).Select(ø => ø.ToString()); var resultat = range.ForEach(Console.WriteLine); Assert.AreEqual(10, resultat.Count()); } Det fungerer fint her! Se resultat: Test : Passed*** ConsoleOutput *** 1 2 3 4 5 6 7 8 9 10 Lenke til kommentar
Svish Skrevet 9. januar 2009 Forfatter Del Skrevet 9. januar 2009 Ja, fant ut av det til slutt. Virker som det har med Deffered Execution å gjøre. Tror koden kjøres hos deg når du bruker Assert.AreEqual(10, resultat.Count()), ettersom Count() vil måtte kjøre igjennom sekvensen for å finne ut hvor mange det er. Uansett synes jeg det var litt teit. kompilatoren kunne jo godt funnet ut at jeg ikke skulle noe mer med den saken, og derfor kjørt den eller noe... men det hadde sikkert blitt kluss det også markerer nå denne som løst uansett, hehe. Lenke til kommentar
The Jackal Skrevet 13. januar 2009 Del Skrevet 13. januar 2009 (endret) Det er helt korrekt at det er pga deferred execution. Grunnen til at det fungerer på denne måten er pga at man blant annet på denne måten i visse tilfeller kan spare en del minnebruk (hvis jeg ikke husker helt riv ruskende galt fra en artikkel av Anders Hejlsberg). IEnumerable er forøvrig ingen collection nødvendigvis (satt litt på spissen kanskje), og derfor er logikken bak ditt første forsøk litt inkonsistent. Endret 13. januar 2009 av The Jackal Lenke til kommentar
Svish Skrevet 13. januar 2009 Forfatter Del Skrevet 13. januar 2009 hvordan inkonsistent? Lenke til kommentar
The Jackal Skrevet 14. januar 2009 Del Skrevet 14. januar 2009 Altså...yield return brukes når du skal kunne bruke funksjonen i en foreach. For at ditt første forsøk skulle fungert, måtte du brukt denne koden: var range = Enumerable.Range(1, 10).Select(ø => ø.ToString()); foreach(int i in range.ForEach(ø => Console.WriteLine(ø))) { <code> } ----------------- Når du bare skriver: range.ForEach(ø => Console.WriteLine(ø)); så oppfører den seg egentlig som: var range = Enumerable.Range(1, 10).Select(ø => ø.ToString()); range er her ikke evaluert enda. Hvis du ønsker å utføre en action på hvert item uten å bruke en foreach, må du som du fant ut, skrive om funksjonen til void og ta bort yield return. Hvis du ønsker å kunne bruke funksjonen i en foreach setning så skal den returnere T og bruke yield return. Litt knotete forklart dette...men du skjønner kanskje Lenke til kommentar
Svish Skrevet 15. januar 2009 Forfatter Del Skrevet 15. januar 2009 aha, ja tror jeg fattet det nå Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå