2008-10-11 18 views
14

Estoy tratando de pensar en formas inteligentes, claras y simples de escribir código que describa la secuencia de enteros en un rango determinado.¿Cuál es la mejor manera de escribir [0..100] en C#?

He aquí un ejemplo:

IEnumerable<int> EnumerateIntegerRange(int from, int to) 
{ 
    for (int i = from; i <= to; i++) 
    { 
     yield return i; 
    } 
} 

Respuesta

62

Esto ya está en el marco: Enumerable.Range.

Para otros tipos, puede que le interesen las clases de rango en mi biblioteca MiscUtil.

+0

Mal enlace aquí Jon –

+3

@ Sam: funciona para mí, lo que es malo en ello? –

+2

@Sam: ¿Cuál no está funcionando para usted y qué está obteniendo? –

0

He aquí una idea que permite a un trabajo de clase rango con las dos cosas que son discretos y las que no lo son:

class Range<T> where T: IComparable<T> 
{ 
    public T From { get; set; } 
    public T To { get; set; } 

    public Range(T from, T to) { this.From = from; this.To = to; } 

    public IEnumerable<T> Enumerate(Func<T, T> next) 
    { 
     for (T t = this.From; t.CompareTo(this.To) < 0; t = next(t)) 
     { 
      yield return t; 
     } 
    } 

    static void Example() 
    { 
     new Range<int> (0, 100).Enumerate(i => i+1) 
    } 
} 
0

Y si usted piensa que el suministro del empadronador cada vez es molesto, he aquí una clase derivada:

class EnumerableRange<T> : Range<T>, IEnumerable<T> 
    where T : IComparable<T> 
{ 
    readonly Func<T, T> _next; 
    public EnumerableRange(T from, T to, Func<T, T> next) 
     : base(from, to) 
    { 
     this._next = next; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     return Enumerate(this._next).GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this.GetEnumerator(); 
    } 
} 
+1

He encontrado que proporciona una mejor separación para tener una clase Range y una clase RangeIterator distinta. Aparte de cualquier otra cosa, significa que tu Range puede ser inmutable y sellada, lo cual es bueno. La versión en MiscUtil tiene varios métodos (extensión y otros) para ir entre los dos. –

+0

Sí, vi el de MiscUtil. Mi rango podría ser inmutable; la única razón de la mutabilidad, para mí, es que permite inicializadores de objetos C#. Probablemente debería haber ido por la inmutabilidad. –

7

Alternativamente, una interfaz de fluidez de los métodos de extensión:

public static IEnumerable<int> To(this int start, int end) 
{ 
    return start.To(end, i => i + 1); 
} 

public static IEnumerable<int> To(this int start, int end, Func<int, int> next) 
{ 
    int current = start; 
    while (current < end) 
    { 
     yield return current; 
     current = next(current); 
    } 
} 

utilizarse como:

1.To(100) 
+0

Personalmente, me gusta la forma en que el método de extensión se lee mejor. Aunque, tengo un poco de lado suave para los métodos de extensión (los implementé para VB). Nunca entendí por qué la gente de C# no hacía de Range un método de extensión en primer lugar. –

Cuestiones relacionadas