2011-11-17 15 views
22

Aquí hay un poco de código que imprime los cuadrados de los números del 0 al 9:¿Hay un método "upto" en C#?

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

Hacer algo de 0 a N por 1 a través de un bucle for es un lenguaje muy común.

He aquí un método UpTo que expresa lo siguiente:

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

El ejemplo casillas de arriba es ahora:

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

Mi pregunta es, ¿el # librería C estándar vienen con algo parecido a lo anterior UpTo?

Idealmente, me gustaría una manera de tener 'UpTo' como método en todos los objetos enteros. Entonces podría hacer:

var n = 10; 

n.UpTo(...); 

¿Es esto posible en C#?

+13

Puede ser una cuestión de gusto, pero considero que la variante 'for' es un poco más legible que' UpTo'. Además, es extremadamente fácil modificar el número de inicio ('0') o el método de incremento (' i ++ ') en la variante' for'. Creo que [los comentarios de Eric Lippert sobre un método 'ForEach'] (http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx) se aplican aquí también. – Heinzi

+1

@Heinzi ¡Gracias por el enlace al artículo de Eric! – dharmatech

+1

.NET Extensions Methods (http://dnpextensions.codeplex.com/) tiene un método de extensión para esto. '5.times (...);' – Jalal

Respuesta

49

convertirlo en un extension method (nótese el este antes de que el parámetro n, que define el tipo este método funciona en):

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

Uso:

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

Nota: La llamada al método anterior no es particularmente intuitiva. Recuerde que el código se escribe una vez y se lee muchas veces.

Tal vez permitir algo por debajo podría ser un poco mejor, pero para ser sincero, aún escribiría un bucle foreach.

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

Si desea esto, entonces usted podría escribir un método de extensión de esta manera:

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

Cambio <-<= si quieres una cota superior inclusiva.

+0

Me has superado a tiempo: ¡votado! :) – Marco

+6

Sé que esto es lo que el OP solicitó, pero la sintaxis apesta: '10.UpTo (i => Console.WriteLine (i * i));' ... Eso no tendría sentido para mí, excepto para el hecho de que sé los métodos de extensión y los trucos sucios que ofrecen :) –

+0

@ MerlynMorgan-Graham: Tomó nota. –

24

Tome un vistazo a LINQ TakeWhile o para su caso específico de números enteros, utilice Enumerable.Range

Enumerable.Range(1, 10).Select(i => ...); 

Podría decirse que no se debe poner una acción en el extremo allí, ver comments on ForEach here.

10

Prueba esto:

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

Con esto se podría escribir

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

La función que escribí se llama un método extensión.
En el momento del diseño, notará que no es una función nativa porque tiene un ícono diferente.
Los métodos Estension son métodos estáticos o funciones incluidas en una clase estática y tipo en el que trabajan es el primer parámetro en el que debe usar la palabra clave this.
En la clase IntExtensions puede escribir todos los métodos que desee; Agruparlos dentro de la misma clase estática te permite administrarlos fácilmente.

+0

¡Respuesta impresionante, gracias Marco! – dharmatech

6

Trate Enumerable.Range, posiblemente en combinación con Take o 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); 
} 

Hay una ForEach en List<T> que se puede utilizar para obtener la sintaxis más cerca de lo que quiere, pero considero que es de mala educación. Requiere una sintaxis pura de consulta/filtro/transformación, que funciona de manera efectivamente inmutable e introduce efectos colaterales.

Para su diversión futura, puede consultar extension methods, IEnumerable<T> y yield return. Mucha funcionalidad de generador y una sintaxis interesante se hacen posibles cuando se combinan estas tres cosas. Aunque yo diría que este ejemplo en particular no es el mejor lugar para usarlos porque la sintaxis resultante se convierte en un desastre.

2

Haga su método como este en una clase estática "Extensiones", por ejemplo:

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

Y el uso:

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

Espero que esto ayude! :)

8

¿quieres hacerlo en una línea? aquí va:

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

Respuesta genial. :-) – dharmatech

+4

¿Por qué se requiere ToList()? –

+5

Se requiere 'ToList()' para llamar a 'ForEach' ya que solo está expuesto en listas y matrices. –

Cuestiones relacionadas