2011-11-17 21 views
22

Oto fragment kodu, który drukuje kwadraty liczb od 0 do 9:Czy istnieje metoda "upto" w języku C#?

for (int i = 0; i < 10; i++) 
    Console.WriteLine(i*i); 

Uprawiając od 0 do n o 1 przez for pętli jest bardzo częstym idiom.

Oto metoda UpTo które wyraża w ten sposób:

class MathUtil 
{ 
    public static void UpTo(int n, Action<int> proc) 
    { 
     for (int i = 0; i < n; i++) 
      proc(i); 
    } 
} 

Powyższy przykład kwadraty jest teraz:

MathUtil.UpTo(10, (i) => Console.WriteLine(i * i)); 

Moje pytanie brzmi, czy średnia # biblioteka C pochodzić z czymś powyższym UpTo?

Idealnie chciałbym, aby metoda "UpTo" była metodą dla wszystkich obiektów całkowitych. Więc mógłbym zrobić:

var n = 10; 

n.UpTo(...); 

Czy to możliwe w języku C#?

+13

Może to być kwestia gustu, ale uważam wariant "za" za nieco bardziej czytelny niż "UpTo". Ponadto bardzo łatwo jest zmodyfikować numer początkowy ('0') lub metodę inkrementacji (' i ++ ') w wariancie' for'. Sądzę, że mają tu również zastosowanie komentarze Eric Lipperta dotyczące metody "ForEach'" (http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx). – Heinzi

+1

@Heinzi Dzięki za link do artykułu Erica! – dharmatech

+1

Metody rozszerzeń .NET (http://dnpextensions.codeplex.com/) mają metodę rozszerzenia. '5times (...);' – Jalal

Odpowiedz

49

przekształcić go w extension method (zwróć uwagę na ten przed parametrem n, który określa typ ta metoda działa on):

static class MathUtil 
{ 
    public static void UpTo(this int n, Action<int> proc) 
    { 
     for (int i = 0; i < n; i++) 
      proc(i); 
    } 
} 

Zastosowanie:

10.UpTo((i) => Console.WriteLine(i * i)); 

Uwaga: Powyższe wywołanie metody nie jest jednak szczególnie intuicyjne. Pamiętaj, że kod jest zapisywany raz i czytany wiele razy.

Możliwe, że dopuszczenie czegoś podobnego może być nieco lepsze, ale szczerze mówiąc, wciąż piszę pętlę foreach.

0.UpTo(10 /*or 9 maybe*/, (i) => Console.WriteLine(i * i)); 

Jeśli chcesz to, to można napisać metodę rozszerzenia takiego:

public static void UpTo(this int start, int end, Action<int> proc) 
{ 
    for (int i = start; i < end; i++) 
     proc(i); 
} 

Zmień < do <= jeśli chcesz integracyjnego górnej granicy.

+0

Biłaś mnie na czas: przegłosowano! :) – Marco

+6

Wiem, o co prosił OP, ale składnia śmierdzi: '10.UpTo (i => Console.WriteLine (i * i));' ... To nie ma sensu dla mnie, z wyjątkiem fakt, że znam metody rozszerzania i brudne sztuczki, na które stać :) –

+0

@ MerlynMorgan-Graham: Noted. –

10

Spróbuj tego:

public static class IntExtensions 
{ 
    public static void UpTo(this int n, Action<int> proc) 
    { 
     for (int i = 0; i < n; i++) 
      proc(i); 
    } 
} 

Z tego można napisać

10.UpTo(i => Console.WriteLine(i * i)); 

Funkcja napisałem nazywa metodę przedłużacza.
W czasie projektowania zauważysz, że nie jest to funkcja natywna, ponieważ ma inną ikonę.
Metody estymacji to statyczne metody lub funkcje zawarte w klasie statycznej i typu, nad którym pracują, jest pierwszym parametrem, w którym należy użyć słowa kluczowego this.
W klasie IntExtensions możesz napisać wszystkie zalecane metody; zgrupowanie ich w obrębie tej samej klasy statycznej ułatwia zarządzanie nimi.

+0

Niesamowita odpowiedź, dzięki Marco! – dharmatech

6

Spróbuj Enumerable.Range, ewentualnie w połączeniu z Take lub TakeWhile:

IEnumerable<int> values = Enumerable.Range(0, 20) 
    .Take(10); // Not necessary in this example 

foreach(var value in values) 
{ 
    Console.WriteLine(value); 
} 

// or ... 

foreach(var i in Enumerable.Range(0, 10)) 
{ 
    Console.WriteLine(i * i); 
} 

Jest ForEach na List<T>, które można wykorzystać, aby zbliżyć się do składni, co chcesz, ale uważam, że to zła forma. Zajmuje czystą składnię zapytania/filtru/transformacji, która działa w sposób niezmienny i wprowadza efekty uboczne.

Dla twojej przyszłej rozrywki możesz sprawdzić: extension methods, IEnumerable<T> i yield return. Wiele funkcji typu generator i interesująca składnia stają się możliwe, gdy używasz tych trzech rzeczy w połączeniu. Chociaż twierdzę, że ten konkretny przykład nie jest najlepszym miejscem do ich użycia, ponieważ wynikowa składnia staje się bałaganem.

2

Dokonaj metody takie jak to w statycznej klasie "Extensions" na przykład:

public static void UpTo(this int n, Action<int> proc) 
{ 
    for (var i = 0; i < n; i++) 
     proc(i); 
} 

a zużycie:

var n = 10; 
n.UpTo(i => Console.WriteLine(i * i)); 

Nadzieja to pomaga! :)

8

chcesz zrobić to w jednym wierszu? tutaj:

Enumerable.Range(0, 9).Select(i => i * i).ToList().ForEach(j=>Console.WriteLine("%d",j)); 
+1

Fajna odpowiedź. :-) – dharmatech

+4

Dlaczego wymagane jest ToList()? –

+5

"ToList()" jest wymagane, aby wywołać "ForEach", ponieważ jest on dostępny tylko na listach i tablicach. –

Powiązane problemy