usan tipos tipo real rango que numeros hacer datos como c#

real - tipos de datos en c# pdf



¿Hay un tipo de C#para representar un rango entero? (7)

Tengo la necesidad de almacenar un rango entero. ¿Hay un tipo existente para eso en C # 4.0?

Por supuesto, podría escribir mi propia clase con las propiedades int From e int To y construir en la lógica adecuada para garantizar que From <= To . Pero si ya existe un tipo, por supuesto usaré eso.



Como también me faltaban intervalos en C #, implementé una clase Interval completamente genérica que puede incluso ocuparse de intervalos con tipos más complejos, por ejemplo, un intervalo entre dos DateTime , que implica TimeSpan durante los cálculos.

Un ejemplo de caso de uso, donde un elemento GUI representa un intervalo de tiempo:

// Mockup of a GUI element and mouse position. var timeBar = new { X = 100, Width = 200 }; int mouseX = 180; // Find out which date on the time bar the mouse is positioned on, // assuming it represents whole of 2014. var timeRepresentation = new Interval<int>( timeBar.X, timeBar.X + timeBar.Width ); DateTime start = new DateTime( 2014, 1, 1 ); DateTime end = new DateTime( 2014, 12, 31 ); var thisYear = new Interval<DateTime, TimeSpan>( start, end ); DateTime hoverOver = timeRepresentation.Map( mouseX, thisYear ); // If the user clicks, zoom in to this position. double zoomLevel = 0.5; double zoomInAt = thisYear.GetPercentageFor( hoverOver ); Interval<DateTime, TimeSpan> zoomed = thisYear.Scale( zoomLevel, zoomInAt ); // Iterate over the interval, e.g. draw labels. zoomed.EveryStepOf( TimeSpan.FromDays( 1 ), d => DrawLabel( d ) );

Para una representación más amplia de la funcionalidad admitida, consulte las pruebas unitarias .

Bajo las cubiertas, utiliza árboles de expresiones para compilar operaciones de operador de tipo en tiempo de ejecución , que se almacenan en caché, por lo que solo hay un costo la primera vez que se inicializa el tipo.


Escribe un método de extensión como este

public static class NumericExtentions { public static bool InRange(this int value, int from, int to) { if (value >= from && value <= to) return true; return false; } public static bool InRange(this double value, double from, double to) { if (value >= from && value <= to) return true; return false; } }

y luego úsalo elegantemente

if (age.InRange(18, 39)) { //Logic }


Esta implementación, inspirada en la respuesta de @drharris, le permite definir intervalos matemáticos correctos con valores, que pueden ser Inclusivos / Exclusivos.

/// <summary>The Interval class.</summary> /// <typeparam name="T">Generic parameter.</typeparam> public class Interval<T> : IEquatable<Interval<T>> where T : IComparable<T>, IEquatable<T> { public Interval() { } public Interval(IntervalValue<T> minimum, IntervalValue<T> maximum) { this.Minimum = minimum; this.Maximum = maximum; } /// <summary>Minimum value of the interval.</summary> public IntervalValue<T>? Minimum { get; set; } /// <summary>Maximum value of the interval.</summary> public IntervalValue<T>? Maximum { get; set; } /// <summary>Presents the Interval in readable format.</summary> /// <returns>String representation of the Interval</returns> public override string ToString() { var min = this.Minimum; var max = this.Maximum; var sb = new StringBuilder(); if (min.HasValue) sb.AppendFormat(min.Value.ToString(IntervalNotationPosition.Left)); else sb.Append("(-∞"); sb.Append('',''); if (max.HasValue) sb.AppendFormat(max.Value.ToString(IntervalNotationPosition.Right)); else sb.Append("∞)"); var result = sb.ToString(); return result; } /// <summary>Determines if the interval is valid.</summary> /// <returns>True if interval is valid, else false</returns> public bool IsValid() { var min = this.Minimum; var max = this.Maximum; if (min.HasValue && max.HasValue) return min.Value.Value.CompareTo(max.Value.Value) <= 0; return true; } /// <summary>Determines if the provided value is inside the interval.</summary> /// <param name="x">The value to test</param> /// <returns>True if the value is inside Interval, else false</returns> public bool ContainsValue(T x) { if (x == null) throw new ArgumentNullException(nameof(x)); var min = this.Minimum; var max = this.Maximum; var isValid = this.IsValid(); if (!isValid) throw new InvalidOperationException("Interval is not valid."); bool result = true; // (-∞,∞) if (min.HasValue) { if (min.Value.Type == IntervalValueType.Exclusive) result &= min.Value.Value.CompareTo(x) < 0; else if (min.Value.Type == IntervalValueType.Inclusive) result &= min.Value.Value.CompareTo(x) <= 0; else throw new NotSupportedException(); } if (max.HasValue) { if (max.Value.Type == IntervalValueType.Exclusive) result &= max.Value.Value.CompareTo(x) > 0; else if (max.Value.Type == IntervalValueType.Inclusive) result &= max.Value.Value.CompareTo(x) >= 0; else throw new NotSupportedException(); } return result; } public bool Equals(Interval<T> other) { if (other == null) return false; if (ReferenceEquals(this, other)) return true; return this.Minimum?.Equals(other.Minimum) == true && this.Maximum?.Equals(other.Maximum) == true; } public override bool Equals(object obj) { return this.Equals(obj as Interval<T>); } public override int GetHashCode() { unchecked { int hash = (int)2166136261; hash = hash * 16777619 ^ this.Minimum?.GetHashCode() ?? 0; hash = hash * 16777619 ^ this.Maximum?.GetHashCode() ?? 0; return hash; } } } public struct IntervalValue<T> : IEquatable<IntervalValue<T>> where T : IComparable<T>, IEquatable<T> //, IFormattable { private readonly T value; private readonly IntervalValueType type; public IntervalValue(T value, IntervalValueType type) { if (value == null) throw new ArgumentNullException(nameof(value)); this.value = value; this.type = type; } public T Value { get { return this.value; } } public IntervalValueType Type { get { return this.type; } } public bool Equals(IntervalValue<T> other) { return this.value.Equals(other.value) && this.type == other.type; } public override bool Equals(object obj) { return obj is IntervalValue<T> && this.Equals((IntervalValue<T>)obj); } public override int GetHashCode() { unchecked { int hash = (int)2166136261; hash = hash * 16777619 ^ this.value.GetHashCode(); hash = hash * 16777619 ^ this.type.GetHashCode(); return hash; } } internal string ToString(IntervalNotationPosition position) { var notation = this.Type.ToString(position); switch (position) { case IntervalNotationPosition.Left: return string.Format("{0}{1}", notation, this.Value); case IntervalNotationPosition.Right: return string.Format("{0}{1}", this.Value, notation); default: throw new NotSupportedException(); } } } internal static class IntervalValueTypeExtensions { public static string ToString(this IntervalValueType type, IntervalNotationPosition position) { switch (position) { case IntervalNotationPosition.Left: switch (type) { case IntervalValueType.Inclusive: return "["; case IntervalValueType.Exclusive: return "("; default: throw new NotSupportedException(); } case IntervalNotationPosition.Right: switch (type) { case IntervalValueType.Inclusive: return "]"; case IntervalValueType.Exclusive: return ")"; default: throw new NotSupportedException(); } break; default: throw new NotSupportedException(); } } } public enum IntervalValueType { Inclusive, Exclusive } public enum IntervalNotationPosition { Left, Right }


Me pareció mejor rodar el mío. Algunas personas usan Tuple s o Point s, pero al final desea que su Range sea ​​extenso y proporcione algunos métodos prácticos que se relacionan con un Range . También es mejor si es genérico (¿y si necesita un rango de Double s, o un rango de alguna clase personalizada?) Por ejemplo:

/// <summary>The Range class.</summary> /// <typeparam name="T">Generic parameter.</typeparam> public class Range<T> where T : IComparable<T> { /// <summary>Minimum value of the range.</summary> public T Minimum { get; set; } /// <summary>Maximum value of the range.</summary> public T Maximum { get; set; } /// <summary>Presents the Range in readable format.</summary> /// <returns>String representation of the Range</returns> public override string ToString() { return string.Format("[{0} - {1}]", this.Minimum, this.Maximum); } /// <summary>Determines if the range is valid.</summary> /// <returns>True if range is valid, else false</returns> public bool IsValid() { return this.Minimum.CompareTo(this.Maximum) <= 0; } /// <summary>Determines if the provided value is inside the range.</summary> /// <param name="value">The value to test</param> /// <returns>True if the value is inside Range, else false</returns> public bool ContainsValue(T value) { return (this.Minimum.CompareTo(value) <= 0) && (value.CompareTo(this.Maximum) <= 0); } /// <summary>Determines if this Range is inside the bounds of another range.</summary> /// <param name="Range">The parent range to test on</param> /// <returns>True if range is inclusive, else false</returns> public bool IsInsideRange(Range<T> range) { return this.IsValid() && range.IsValid() && range.ContainsValue(this.Minimum) && range.ContainsValue(this.Maximum); } /// <summary>Determines if another range is inside the bounds of this range.</summary> /// <param name="Range">The child range to test</param> /// <returns>True if range is inside, else false</returns> public bool ContainsRange(Range<T> range) { return this.IsValid() && range.IsValid() && this.ContainsValue(range.Minimum) && this.ContainsValue(range.Maximum); } }


Mejorando sobre @andrius-naruševičius una respuesta muy útil para hacerlo más idiomático y fácilmente personalizable

/// <summary> /// http://.com/questions/5343006/is-there-a-c-sharp-type-for-representing-an-integer-range /// </summary> public class Range { readonly static char[] Separators = {'',''}; public static List<int> Explode(int from, int to) { return Enumerable.Range(from, (to-from)+1).ToList(); } public static List<int> Interpret(string input) { var result = new List<int>(); var values = input.Split(Separators); string rangePattern = @"(?<range>(?<from>/d+)-(?<to>/d+))"; var regex = new Regex(rangePattern); foreach (string value in values) { var match = regex.Match(value); if (match.Success) { var from = Parse(match.Groups["from"].Value); var to = Parse(match.Groups["to"].Value); result.AddRange(Explode(from, to)); } else { result.Add(Parse(value)); } } return result; } /// <summary> /// Split this out to allow custom throw etc /// </summary> private static int Parse(string value) { int output; var ok = int.TryParse(value, out output); if (!ok) throw new FormatException($"Failed to parse ''{value}'' as an integer"); return output; } }

y las pruebas:

[Test] public void ExplodeRange() { var output = Range.Explode(5, 9); Assert.AreEqual(5, output.Count); Assert.AreEqual(5, output[0]); Assert.AreEqual(6, output[1]); Assert.AreEqual(7, output[2]); Assert.AreEqual(8, output[3]); Assert.AreEqual(9, output[4]); } [Test] public void ExplodeSingle() { var output = Range.Explode(1, 1); Assert.AreEqual(1, output.Count); Assert.AreEqual(1, output[0]); } [Test] public void InterpretSimple() { var output = Range.Interpret("50"); Assert.AreEqual(1, output.Count); Assert.AreEqual(50, output[0]); } [Test] public void InterpretComplex() { var output = Range.Interpret("1,5-9,14,16,17,20-24"); Assert.AreEqual(14, output.Count); Assert.AreEqual(1, output[0]); Assert.AreEqual(5, output[1]); Assert.AreEqual(6, output[2]); Assert.AreEqual(7, output[3]); Assert.AreEqual(8, output[4]); Assert.AreEqual(9, output[5]); Assert.AreEqual(14, output[6]); Assert.AreEqual(16, output[7]); Assert.AreEqual(17, output[8]); Assert.AreEqual(20, output[9]); Assert.AreEqual(21, output[10]); Assert.AreEqual(22, output[11]); Assert.AreEqual(23, output[12]); Assert.AreEqual(24, output[13]); } [ExpectedException(typeof (FormatException))] [Test] public void InterpretBad() { Range.Interpret("powdered toast man"); }


Solo una pequeña clase que escribí que podría ser útil para alguien:

public class Range { public static List<int> range(int a, int b) { List<int> result = new List<int>(); for(int i = a; i <= b; i++) { result.Add(i); } return result; } public static int[] Understand(string input) { return understand(input).ToArray(); } public static List<int> understand(string input) { List<int> result = new List<int>(); string[] lines = input.Split(new char[] {'';'', '',''}); foreach (string line in lines) { try { int temp = Int32.Parse(line); result.Add(temp); } catch { string[] temp = line.Split(new char[] { ''-'' }); int a = Int32.Parse(temp[0]); int b = Int32.Parse(temp[1]); result.AddRange(range(a, b).AsEnumerable()); } } return result; } }

Entonces solo llamas:

Range.understand("1,5-9,14;16,17;20-24")

Y el resultado se ve así:

List<int> [0]: 1 [1]: 5 [2]: 6 [3]: 7 [4]: 8 [5]: 9 [6]: 14 [7]: 16 [8]: 17 [9]: 20 [10]: 21 [11]: 22 [12]: 23 [13]: 24