111 votes

Est-il de type C# pour la représentation d'un entier de Gamme?

J'ai besoin de stocker un nombre entier de gamme. Est-il un type existant pour qu'en C# 4.0?

Bien sûr, je pourrais écrire ma propre classe avec des int et int De propriétés et de construire en bonne logique, pour assurer qu'<=. Mais si un type existe déjà, je l'avais bien sûr utiliser plutôt que.

145voto

drharris Points 6747

J'ai trouvé qu'il est préférable de rouler mon propre. Certaines personnes utilisent Tuples ou Points, mais en fin de compte, vous voulez que votre Gamme est vaste et de fournir un peu de pratique les méthodes qui ont trait à une Gamme. Il est également préférable si générique (que faire si vous avez besoin d'une gamme de Doubles, ou une gamme de coutume, de classe?) Par exemple:

    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}]", Minimum, Maximum); }

            /// <summary>
            /// Determines if the range is valid
            /// </summary>
            /// <returns>True if range is valid, else false</returns>
            public Boolean IsValid() { return Minimum.CompareTo(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 Boolean ContainsValue(T value)
            {
                    return (Minimum.CompareTo(value) <= 0) && (value.CompareTo(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 Boolean 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 Boolean ContainsRange(Range<T> Range)
            {
                    return this.IsValid() && Range.IsValid() && this.ContainsValue(Range.Minimum) && this.ContainsValue(Range.Maximum);
            }
    }

24voto

rsenna Points 5528

Fonctionne sur C# 3.0:

IEnumerable<int> myRange = Enumerable.Range(1, 10);

Modifier s'il vous Plaît, gardez à l'esprit que:

  • Il n'existe pas (immédiate) de performances en utilisant que - c'est Linq, de sorte que l'exécution est différée.
  • Il existe des méthodes comme l' Min et Max déjà disponibles.
  • IEnumerable expose également à des méthodes comme Contains, Intersect et Union - donc les distances ne peuvent pas seulement être interrogés, ils peuvent également être combinés.
  • Il y a des gens qui utilisent déjà ce pour représenter les plages (plutôt que de simplement les énumérer sur une collection de nombres entiers).

Bien sûr, si par "stocker" l'OP est seulement inquiété de la persistance des données (par opposition à la représentation des données), il pourrait utiliser un simple DTO avec deux champs de type entier.

Encore, il demande "Est-il un type existant pour qu'en C# 4.0?" - et je crois que la réponse est oui, il est, et il est appelé IEnumerable<int>.

Edit 2 Aussi garder à l'esprit qu' Enumerable.Range peut avoir vraiment de la mauvaise performance.

C'est sans doute que la plupart des troubles de la downvoters de cette réponse: il y a usecases où Enumerable.Range n'est pas une option pratique.

Encore, je crois que les éléments suivants doivent également être considérés:

  1. Qu'il est sémantiquement un son moyen de représenter un nombre entier de gamme.
  2. Qu'il peut être utilisé pour de petites plages sans notable des performances.
  3. Que le problème est accidentelle, le sens qu'il est parfaitement possible de retourner un IEnumerable<int> qui est en mesure d'être interrogé en contre, sans avoir à parcourir l'ensemble de la gamme.

Concernant le 3ème point, cette bibliothèque implémente un Sequence.Create méthode d'extension. Il fonctionne de façon similaire à l' Enumerable.Range et renvoie également un IEnumerable<int>, mais il est censé être plus efficace.

8voto

Juste une petite classe, j'ai écrit qui pourraient être utiles à quelqu'un:

    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;
        }
    }

Ensuite, vous appelez simplement:

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

Et le résultat ressemble à ceci:

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

-3voto

jsumners Points 6247

Comment sur une struct?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X