2009-08-14 9 views
8

Je me demandais si le type de structure enum a une limite sur ses membres. J'ai cette très grande liste de "variables" que j'ai besoin de stocker à l'intérieur d'une énumération ou comme des constantes dans une classe mais j'ai finalement décidé de les stocker dans une classe, cependant, je suis un peu curieux de la limite des membres d'une énumération (le cas échéant).Les enum ont-ils une limite de membres en C#?

Alors, les enums ont-ils une limite sur .Net?

+0

Je suis juste curieux de savoir ce que vous faites qui aurait besoin de tant de constantes pour avoir à poser cette question ... – NotDan

+0

Bien sûr, je n'utiliserai pas la limite de taille 2^32 mais j'ai besoin de beaucoup de "stockage" . Nous sommes en train de développer une application qui est liée à l'assurance, donc il y a beaucoup de variables qui doivent être là pour faire la note pour obtenir une prime et comme vous pouvez l'imaginer il y en a beaucoup (probablement 600 à 1 000) –

Répondre

16

Oui. Le nombre de membres avec des valeurs distinctes est limité par le type sous-jacent de enum - par défaut c'est Int32, donc vous pouvez obtenir autant de membres différents (2^32 - je trouve difficile que vous atteigniez cette limite), mais vous pouvez spécifier explicitement le type sous-jacent comme celui-ci:

enum Foo : byte { /* can have at most 256 members with distinct values */ } 

Bien sûr, vous pouvez avoir autant de membres que vous voulez s'ils ont tous la même valeur:

enum { A, B = A, C = A, ... } 

Dans les deux cas, il y a probablement une certaine limite définie par l'implémentation dans le compilateur C#, mais je voudrais ex pect qu'il soit MIN (range-of-Int32, free-memory), plutôt qu'une limite stricte.

+0

Merci, je ne savais pas que vous pouviez déclarer le type sous-jacent d'une énumération. –

7

En raison d'une limite dans le format de fichier PE, vous ne pouvez probablement pas dépasser quelque 100 000 000 de valeurs. Peut-être plus, peut-être moins, mais certainement pas un problème.

+0

bon point. –

6

De l'C# Language Specification 3.0, 1.10:

Un format de stockage de type ENUM et gamme de valeurs possibles sont déterminées par son type sous-jacent.

Bien que je ne suis pas 100% sûr que je pense compilateur Microsoft C# ne permettant valeurs enum non négatives, donc si le type sous-jacent est un Int32 (il est, par défaut) alors j'attendre environ 2^31 valeurs possibles, mais il s'agit d'un détail d'implémentation car il n'est pas spécifié. Si vous avez besoin de plus que cela, vous faites probablement quelque chose de mal.

+1

Les nombres négatifs sont autorisés tant que vous ne spécifiez pas explicitement un type sous-jacent non signé: Invalide = -1, Aucun = 0, OptionA = 1, ... –

1

Vous pouvez théoriquement utiliser int64 comme type de base dans l'énumération et obtenir 2^63 entrées possibles. D'autres vous ont donné d'excellentes réponses à ce sujet.

Je pense qu'il ya une deuxième question implicite de si vous utilisez une énumération pour quelque chose avec un grand nombre d'éléments. Cela s'applique directement à votre projet de plusieurs façons. L'une des considérations les plus importantes serait la maintenabilité à long terme. Pensez-vous que l'entreprise va changer la liste des valeurs que vous utilisez? Si oui, doit-il y avoir rétrocompatibilité avec les listes précédentes? Quelle est l'importance d'un problème? En général, plus le nombre de membres dans une énumération est élevé, plus il est probable que la liste devra être modifiée à une date ultérieure.

Les enums sont parfaits pour beaucoup de choses. Ils sont propres, rapides et simples à mettre en œuvre. Ils fonctionnent très bien avec IntelliSense et facilitent le travail du programmeur suivant, surtout si les noms sont clairs, concis et, si nécessaire, bien documentés.

Le problème est qu'une énumération comporte également des inconvénients. Ils peuvent être problématiques s'ils doivent être modifiés, surtout si les classes qui les utilisent sont conservées au stockage.

Dans la plupart des cas, les enums sont conservés dans le stockage en tant que valeurs sous-jacentes, et non en tant que noms conviviaux.

enum InsuranceClass 
    { 
    Home,  //value = 0 (int32) 
    Vehicle, //value = 1 (int32) 
    Life,  //value = 2 (int32) 
    Health //value = 3 (int32) 
    } 

Dans cet exemple, la valeur InsuranceClass.Life obtiendrait persisté en tant que numéro 2.

Si un autre programmeur fait un petit changement au système et ajoute à l'animal de compagnie ENUM comme celui-ci;

enum InsuranceClass 
    { 
    Home,  //value = 0 (int32) 
    Vehicle, //value = 1 (int32) 
    Pet,  //value = 2 (int32) 
    Life,  //value = 3 (int32) 
    Health //value = 4 (int32) 
    } 

Toutes les données qui sortent du stockage affiche maintenant la vie politiques comme politiques Animaux. C'est une erreur extrêmement facile à faire et peut introduire des bogues difficiles à localiser.

Le deuxième problème majeur avec enums est que chaque modification des données vous obligera à reconstruire et redéployer votre programme. Cela peut causer divers degrés de douleur. Sur un serveur Web, ce n'est peut-être pas un gros problème, mais s'il s'agit d'une application utilisée sur 5000 systèmes de bureau, vous avez un coût totalement différent pour redéployer votre modification de liste mineure.

Si votre liste est susceptible de changer périodiquement, vous devriez vraiment envisager un système qui stocke cette liste sous une autre forme, très probablement en dehors de votre code. Les bases de données ont été spécialement conçues pour ce scénario ou même un simple fichier de configuration pourrait être utilisé (pas la solution préférée). Une planification intelligente des modifications peut réduire ou éviter les problèmes associés à la reconstruction et au redéploiement de votre logiciel. Ceci n'est pas une suggestion pour optimiser prématurément votre système pour la possibilité de changement, mais plutôt une suggestion pour structurer le code afin qu'un changement probable dans le futur ne crée pas un problème majeur. Des situations différentes nécessiteront des décisions différentes.

Voici mes approximatives règles d'utilisation des enums;

  1. Utilisez-les pour classifier et définir d'autres données, mais pas comme données elles-mêmes. Pour être plus clair, j'utiliserais InsuranceClass.Life à déterminer comment les autres données d'une classe devraient être utilisées, mais je ne pas faire la valeur sous-jacente de {pseudocode} InsuranceClass.Life = $653.00 et utiliser la valeur elle-même dans les calculs. Les enums ne sont pas des constantes. Faire cela crée de la confusion.
  2. Utilisez enums lorsque la liste d'énumération est peu susceptible de changer. Enums sont grands pour les concepts fondamentaux mais pauvres pour les idées en constante évolution. Lorsque vous créez une énumération, il s'agit d'un contrat avec les futurs programmeurs que vous voulez éviter de casser.
  3. Si vous devez changer une enum, alors avoir une règle tout le monde suit que vous ajoutez à la fin, pas le milieu. L'alternative est que vous définir des valeurs spécifiques à chaque énumération et ne jamais les modifier. Le point est que vous avez peu de chance de savoir comment les autres utilisent vos valeurs sous-jacentes et les changer peut causer de la misère pour n'importe qui d'autre utilisant votre code . C'est un ordre de grandeur plus important pour tout système qui persiste des données.
  4. Le corollaire de # 2 et # 3 est de ne jamais supprimer un membre d'une énumération. Il existe des cercles d'enfer spécifiques pour les programmeurs qui le font dans une base de code utilisée par d'autres.

Espérons que cela s'est étendu sur les réponses d'une manière utile.