2012-09-14 5 views
2

Dites que j'ai une fonction qui prend un entier comme argument. J'aimerais pouvoir utiliser une liste énumérée pour conserver les valeurs entières organisées.Passage des valeurs énumérées aux fonctions

Par exemple, je voudrais idéalement pouvoir définir ces (pseudo-code):

public enum days 
{ 
    monday, 
    tuesday, 
    etc... 
} 

public enum months 
{ 
    january, 
    february, 
    etc... 
} 

int doSomething(enum x) 
{ 
    return x + 1; 
} 

et être en mesure d'appeler la fonction en utilisant soit des listes énumérées comme suit:

int a = doSomething(days.monday); 
int y = doSomething(months.february); 

Cela évidemment ne fonctionnera pas comme-est parce que les besoins doSomething à définir en utilisant seulement l'un des énumérations (à savoir soit des jours ou des mois). Je connais quelques options. L'un est simplement jeté un int:

int a = doSomething((int)days.monday); 
int y = doSomething((int)months.february); 

Le seul problème est que cette fonction est appelée place beaucoup dans mon code, et il est maladroit de devoir continuer à mettre « (int) » s dans le place (l'une des principales motivations pour grouper ces valeurs int ensemble en enums est en premier lieu de rendre le code plus lisible).

Une autre option est d'éviter énumérations tout à fait, et regrouper plutôt les valeurs dans une classe de conteneur, quelque chose comme:

static class Days 
{ 
    static int x = 0; 

    static int monday = x++; 
    static int tuesday = x++; 
} 

Encore une fois, cela fonctionnera mais juste semble terriblement lourd quand j'ai beaucoup de ces conteneurs classes à définir.

La réponse pourrait très bien être qu'il n'y a pas de façon plus simple, et que je dois être un adulte et juste accepter une de ces options. Mais je pensais que j'obtiendrais un contrôle de santé avant de m'y engager. Y a-t-il une troisième option?

Répondre

2

Quel est votre problème?

public enum Days : short 
{ 
    Monday = 1, 
    Tuesday = 2, 
    ... 
} 

DoSomething(Days.Monday); 

void DoSomething(Days day) 
{ 
    Days nextDay = day + 1; 
} 

Notez également already built-in enum System.DayOfWeek.


Je me suis point OP, mais autant que je sache ce n'est pas supporté par C# encore:

void DoSomething<T>(T e) where T : enum 
{ 
    T next = e + 1; 
} 
+0

Wrt au System.DayOfWeek, les mois et les valeurs que je utilise jour ne sont que des exemples. Dans la vraie application, ils ne sont pas liés du tout à des jours ou des heures. Pour le code que vous avez montré, la fonction DoSomething() ne pourra fonctionner que sur l'énumération Days. Si j'essaie de fournir une énumération différente, cela échouera. – Gadzooks34

+0

@ Gadzooks34: J'ai compris. Mais malheureusement, C# ne supporte pas encore la contrainte générique par enum. Voir ma mise à jour post pour la description. – abatishchev

0

oui vous pouvez le faire

public enum days : int 
{ 
    monday, 
    tuesday, 
    ... 
} 

automatiquement lundi devient 0 et mardi devient 1 et ainsi sur

public enum months : int 
{ 
    january, 
    february, 
    ... 
} 

même pendant des mois

int doSomething(Enum x) 
{ 
    return (int)x + 1; 
} 

et l'appeler comme

int a = doSomething(days.monday); 

ou appelez comme

int a = doSomething(months.january); 

maintenant days.monday equals 0 et après la méthode a devient 1.

+1

Ça a l'air génial mais ça ne marche pas. Le compilateur se plaindra que doSomething() a un argument invalide, même lorsque l'enum est dérivé de int. – Gadzooks34

+0

@ Gadzooks34: Comment est-ce maintenant? –

+0

Eh bien, c'est de retour à ce que j'ai mis dans mon exemple. Oui, lancer à un int dans la fonction fonctionnera, c'est juste plus maladroit que je le voudrais. – Gadzooks34

0

Tout problème avec System.DateTime?

Ce serait le type le plus pragmatique à utiliser.

+0

J'utilise seulement ces valeurs comme exemples. Ils ne sont pas réellement liés à la journée/l'heure dans la vraie application. – Gadzooks34

0

Vous pourriez surcharger votre méthode, si vous voulez juste la valeur int, peut-être quelque chose comme ça?

int dosomething(enum x) 
{return dosomething((int)x)} 
int dosomething(int x) 
{return x+1} 
+0

J'ai essayé mais je ne pense pas que vous puissiez réellement définir la fonction comme ça. Définir doSomething (enum x) s'attend à ce que toute l'énumération soit passée, pas seulement une de ses valeurs, ce qui n'est pas ce que je veux (désolé si cela n'était pas clair de mon pseudo-code). – Gadzooks34

+0

Désolé, ce que j'essayais de suggérer, c'est que vous avez une surcharge pour chaque énumération, par ex. 'dosomething (jours x)' 'dosomething (mois x)' le problème est que cela pourrait devenir important si vous avez beaucoup d'enums différents. – Sconibulus

+0

Oui. Le problème est que la fonction est définie dans une bibliothèque de base et que les utilisateurs définissent leurs propres énumérations sans avoir accès au code source de la fonction. – Gadzooks34

0

Ou si vous ne voulez pas changer toutes les énumérations existantes:

public static int DoSomething(Enum x) 
    { 
     int xInt = (int)Convert.ChangeType(x, x.GetTypeCode()); 
     DoSomething(xInt); 
    } 

comme indiqué ici: enums-returning-int-value

+0

C'est un truc très cool. Je pense que cela fonctionnera. La seule chose qui m'inquiète, c'est la performance (même si je n'ai pas mentionné cela dans ma question). On dirait que la conversion peut être lente: [version plus rapide de Convert.ChangeType] (http://stackoverflow.com/questions/1532197/faster-version-of-convert-changetype) – Gadzooks34

+0

bien si la performance d'exécution est plus importante que je suggère quelque chose sur la ligne des génériques, cher quelque part ailleurs mais mieux sur la performance. –

0

vous essayez de surcharger a fait une fonction par le paramètre:

int DoSomething(Enum1 value) 
int DoSomething(Enum2 value) 
+0

S'il vous plaît voir ma réponse à Sconibulus. – Gadzooks34

0
public enum days : int 
{ monday, tuesday, 

} 

public enum months :int 
{ january, february, march, 

} 

public int doSomething(int z) 
{ 
    return z + 1; 
} 

// votre méthode d'appel int c = ee.doSomething ((int) testenums.months.march); int c = ee.doQuelque chose ((int) testenums.day.February);

code de travail que vous avez toujours passer ENUM et qui est de type int vous avez juste besoin d'analyser et d'envoyer ce code fonctionne parfaitement .. laissez-moi savoir

+0

Je crois que si vous copiez et collez votre code dans l'ide, vous constaterez que cela ne fonctionne pas, et à la place donne le problème que je décris (l'argument function doSomething() est de type invalide). – Gadzooks34

+0

pourquoi cela ne fonctionnera pas .. Son un code de travail vous pourquoi retournerait-il un type d'argument invalide .. vous avez juste besoin de regarder dedans. int c = ee.doSomething ((int) testenums.months.march), vérifiez votre type d'enum est-il court ou int – Praveen

0

J'ai passé un temps « peu » à ce sujet, parce obtenu un même problème (solution). Voici donc ma solution qui fonctionne très bien sur (.NET 4), Windows Forms:

VB:NET 

      Private Function DoSomething(Of TEnum As {IComparable, IConvertible, IFormattable})(ByVal valueEnum As TEnum) As Int32 

       Dim i As Int32 = CInt(Convert.ChangeType(valueEnum, valueEnum.GetTypeCode())) 
       //Do something with int 
       i += 1 
       Return i 

      End Function 

    C# 

     private int DoSomething<TEnum>(TEnum valueEnum) where TEnum: IComparable, IConvertible, IFormattable 
        { 
         int i = 0; 
         i = (int)Convert.ChangeType(valueEnum, valueEnum.GetTypeCode()); 
         i++; 
         return i; 
        } 
Questions connexes