2010-01-14 3 views
1

J'ai une énumération qui énumère les valeurs entières renvoyées par une API externe pour une utilisation plus facile dans mon code. Mais je ne connais pas nécessairement les valeurs entières au moment de la compilation, donc j'ai du code qui les relie au démarrage du programme et les stocke dans un dictionnaire.C# empêche la conversion en int

J'ai défini des méthodes d'extension pour la conversion vers/depuis les codes entiers, mais ces codes entiers ne sont pas les mêmes que ceux qui seraient renvoyés d'un cast vers int. Si un autre programmeur devait programmer avec mon énumération, j'ai peur qu'ils essaieraient d'aller et de sortir des entiers hors de l'habitude. Et le programme accepterait simplement le mauvais code.

Existe-t-il un moyen d'empêcher la conversion explicite de mon énumération en/de int? Sinon, existe-t-il un moyen de provoquer une exception si quelqu'un tente? Ou connecter mes propres fonctions de conversion? Ou changer la valeur sous-jacente d'une énumération au moment de l'exécution?

+0

Utiliser des chaînes à la place? –

+1

Ou faites en sorte que les codes entiers DO correspondent. Pourquoi n'est-ce pas une possibilité? – Aaronaught

+0

Les chaînes n'ont pas pu être vérifiées lors de la compilation ... J'ai une poignée de codes entiers que je connais, donc oui, je pourrais coder mes énumérations à ces valeurs. Mais il est possible que l'API change leurs valeurs dans le futur, etc. Je pourrais juste le coder en dur et traiter les problèmes comme ils se produisent, mais c'est un problème de programmation intéressant que j'espère avoir une réponse intéressante. –

Répondre

10

Ce que vous essayez est très "sale".

Utilisez une classe statique avec des valeurs readonly au lieu des enums. Vous pouvez ensuite initialiser les valeurs du type initialiseur (ou via une méthode statique):

public static class Foos 
{ 
    public static readonly int First; 
    public static readonly int Second; 

    //... 

    static Foos() 
    { 
     //For Example: 
     First = DateTime.Now.Day; 
     First = DateTime.Now.Month; 
    } 
} 
+1

Très, très sale en effet. – GalacticCowboy

+0

Je voulais éviter d'utiliser une classe comme celle-là, mais je pourrais tout simplement opter pour cela, en fonction des difficultés que j'ai rencontrées. –

+1

Si l'on veut pouvoir utiliser des variables du type en question (plutôt que 'int'), on pourrait utiliser une structure qui supporte les conversions depuis ou vers' Int32'. – supercat

1

Une autre façon de faire ce qui pourrait donner un sens: définir le Enum dans votre programme et la carte des valeurs de l'API externe au Enum dans des méthodes privées. En d'autres termes, n'exposez le type de l'API externe nulle part dans votre modèle objet. Par exemple:

public enum MyEnum { First, Second, Third }; 

public class MyApiWrapper 
{ 
    private Dictionary<int, int> ExternalToInternal = new Dictionary<int, int>(); 
    private Dictionary<int, int> InternalToExternal = new Dictionary<int, int>(); 

    public MyApiWrapper(List<int> externalApiEnumValues) 
    { 
     foreach (int i = 0; i < externalApiEnumValues.Count; i++) 
     { 
     ExternalToInternal[externalApiEnumValues[i]] = i; 
     InternalToExternal[i] = externalApiEnumValues[i]; 
     } 
    } 

    // obviously, your real method for calling the external API 
    // will do more than this. 
    public void CallApi() 
    { 
     CallExternalApi(_EnumValue); 
    } 

    private MyEnum _ExternalEnumValue; 
    public MyEnum EnumValue 
    { 
     get { return ExternalToInternal[_ExternalEnumValue]; } 
     set { _ExternalEnumValue = InternalToExternal[value]; } 
    } 
} 

Tant que tous les accès à l'API est fait par cette classe (on espère que vous avez déjà accès API encapsulé externe dans une classe), vous pouvez utiliser librement MyEnum partout dans votre application sans être préoccupé par ce que les autres programmeurs font avec les valeurs.

+0

Malheureusement, il s'agit d'une grande base de code héritée, donc il n'y a pas un seul point d'étranglement comme ça. Il y a des appels partout. J'essaie de mordre des morceaux gérables et de les refactoriser, mais je continue à courir dans des situations comme celle-ci où je ne peux pas tout réparer à la fois et je ne peux pas garantir que les autres codeurs ne continueront pas de mauvaises habitudes. –