2012-04-16 9 views
5

Tenemos muchos códigos que tienen valores "mínimos" y "máximos" para cosas como precios, ganancias, costos, etc. En la actualidad, estos se pasan como dos parámetros a los métodos y a menudo tienen diferentes propiedades/métodos para recuperarlos.¿Hay una clase estándar para representar un "rango" en .net?

He visto 101 clases personalizadas para almacenar rangos de valores en diferentes bases de código durante las últimas décadas, antes de crear otra clase más, deseo confirmar que el framework .NET actualmente no tiene tales una clase construida en en alguna parte.

(I saber cómo crear mi propia clase, si es necesario, pero tenemos demasiadas ruedas en este mundo ya que me acaba de inventar antera en un capricho)

Respuesta

5

Eso es correcto, no hay construyeron -en clase en C# o BCL para rangos. Sin embargo, hay TimeSpan en BCL para representar períodos de tiempo, que puede componer adicionalmente con DateTime para representar un rango de veces.

+1

¿Por qué fue esto downvoted? – jason

+0

Los votos negativos sobre esto me confunden. – jason

+0

También recibí dos votos abajo inexplicables. Bastante molesto. +1 de mí para compensar. – Steven

6

AFAIK no existe nada en .NET. Sería interesante, sin embargo, para llegar a una implementación genérica.

La construcción de un tipo de gama BCL calidad genérico es mucho trabajo, pero podría ser algo como esto:

public enum RangeBoundaryType 
{ 
    Inclusive = 0, 
    Exclusive 
} 

public struct Range<T> : IComparable<Range<T>>, IEquatable<Range<T>> 
    where T : struct, IComparable<T> 
{ 
    public Range(T min, T max) : 
     this(min, RangeBoundaryType.Inclusive, 
      max, RangeBoundaryType.Inclusive) 
    { 
    } 

    public Range(T min, RangeBoundaryType minBoundary, 
     T max, RangeBoundaryType maxBoundary) 
    { 
     this.Min = min; 
     this.Max = max; 
     this.MinBoundary = minBoundary; 
     this.MaxBoundary = maxBoundary; 
    } 

    public T Min { get; private set; } 
    public T Max { get; private set; } 
    public RangeBoundaryType MinBoundary { get; private set; } 
    public RangeBoundaryType MaxBoundary { get; private set; } 

    public bool Contains(Range<T> other) 
    { 
     // TODO 
    } 

    public bool OverlapsWith(Range<T> other) 
    { 
     // TODO 
    } 

    public override string ToString() 
    { 
     return string.Format("Min: {0} {1}, Max: {2} {3}", 
      this.Min, this.MinBoundary, this.Max, this.MaxBoundary); 
    } 

    public override int GetHashCode() 
    { 
     return this.Min.GetHashCode() << 256^this.Max.GetHashCode(); 
    } 

    public bool Equals(Range<T> other) 
    { 
     return 
      this.Min.CompareTo(other.Min) == 0 && 
      this.Max.CompareTo(other.Max) == 0 && 
      this.MinBoundary == other.MinBoundary && 
      this.MaxBoundary == other.MaxBoundary; 
    } 

    public static bool operator ==(Range<T> left, Range<T> right) 
    { 
     return left.Equals(right); 
    } 

    public static bool operator !=(Range<T> left, Range<T> right) 
    { 
     return !left.Equals(right); 
    } 

    public int CompareTo(Range<T> other) 
    { 
     if (this.Min.CompareTo(other.Min) != 0) 
     { 
      return this.Min.CompareTo(other.Min); 
     } 

     if (this.Max.CompareTo(other.Max) != 0) 
     { 
      this.Max.CompareTo(other.Max); 
     } 

     if (this.MinBoundary != other.MinBoundary) 
     { 
      return this.MinBoundary.CompareTo(other.Min); 
     } 

     if (this.MaxBoundary != other.MaxBoundary) 
     { 
      return this.MaxBoundary.CompareTo(other.MaxBoundary); 
     } 

     return 0; 
    } 
} 
+0

¿Pueden los downvoters explicar su downvote? – Steven

+0

Bueno, no te he votado negativamente, pero lo que no me gusta aquí es forzar a T a ser struct? ¿Por qué tal restricción? Otra cosa es que el rango en sí no debe ser struct. Struct es bueno cuando ocupa menos memoria que un puntero (entonces es eficiente - copiando). Esta clase obviamente toma más de 4 u 8 bytes. – dzendras

+0

@dzendras: estoy de acuerdo con sus comentarios. La idea era proporcionar la semántica del tipo de valor de tipo, así que elegí 'struct', pero no tiene que ser así. Tenga en cuenta que las directrices de diseño del marco aconsejan que los tipos de valores sean menores que 16 bytes, por lo que no 8 o 4, pero el rango puede ser fácilmente de 16 bytes o mayor, por ejemplo cuando se usa un 'Rango '. – Steven

1

he empezado a hacer mi propia.

public class Range<T> where T : IComparable 
{ 
    private readonly T start; 

    private readonly T end; 

    public Range(T start, T end) 
    { 
     if (start.CompareTo(end) < 0) 
     { 
      this.start = start; 
      this.end = end; 
     } 
     else 
     { 
      this.start = end; 
      this.end = start; 
     } 
    } 

    public T Start 
    { 
     get 
     { 
      return this.start; 
     } 
    } 

    public T End 
    { 
     get 
     { 
      return this.end; 
     } 
    } 

    public static bool Intersect(Range<T> a, Range<T> b) 
    { 
     return !(b.Start.CompareTo(a.End) > 0 || a.Start.CompareTo(b.End) > 0); 
    } 

    public bool Intersect(Range<T> other) 
    { 
     return Intersect(this, other); 
    } 
} 
Cuestiones relacionadas