Dériver un énuméré [Résolu]

Signaler
Messages postés
3
Date d'inscription
mardi 12 février 2008
Statut
Membre
Dernière intervention
27 avril 2009
-
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
-
Bonjour à tous,

J'aurais besoin de dériver un énuméré.
En fait dans l'énuméré fille il faut que j'ai accès aux "attributs" de l'énuméré mère.

Si j'ai
       

publicenum EnumMere
{
Un = 1,
Deux = 2,
Trois = 3
}

publicenum EnumFille
{
Quatre = 4,
Cinq = 5
}

je voudrais pouvoir faire ça par exemple :
EnumFille.Un

Je ne sais pas si je suis très clair, n'hésitez pas à demander des précisions.

18 réponses

Messages postés
834
Date d'inscription
samedi 15 novembre 2008
Statut
Membre
Dernière intervention
14 janvier 2017
30
Grrr,
je reposte pour la gestion des espaces !!!!

public
class Mere
{

public 
static 
readonly 
int  Un = 1;

public 
static 
readonly 
int  Deux = 2;

public 
static 
readonly 
int  Trois = 3;
}

public
class Fille : Mere
{

public 
static 
readonly 
int  Quatre = 4;

public 
static 
readonly 
int  Cinq = 5;
}

C# is amazing, enjoy it!
Messages postés
3
Date d'inscription
mardi 12 février 2008
Statut
Membre
Dernière intervention
27 avril 2009

C'est exactement ce que j'ai trouvé comme solution et ca à l'air de convenir à tous les besoins du projet.

Merci quand même a vous pour votre rapidité ;)

A bientot ici:
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
44
Salut

A ma connaissance ce n'est pas possible.
Une alternative que je vois serait d'utiliser des membres static en lecture seule (ou une propriété, ça revient au même)

    public class Mere
    {
        protected int val;
        protected Mere(int i)
        {
            val = i;
        }

        public int Val
        {
            get { return val; }
        }

        public static readonly Mere Un = new Mere(1);
        public static readonly Mere Deux = new Mere(2);
        public static readonly Mere Trois = new Mere(3);
    }

    public class Fille : Mere
    {
        protected Fille(int i) : base(i) { }

        public static readonly Fille Quatre = new Fille(4);
        public static readonly Fille Cinq = new Fille(5);
    }

Bon, je te l'accorde, c'est plus long. Mais après, tu peux utiliser la classe Mere pour 1 à 3 et la classe Fille pour 1 à 5 (utilise la propriété Val de ton objet pour récupérer sa valeur)

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Messages postés
834
Date d'inscription
samedi 15 novembre 2008
Statut
Membre
Dernière intervention
14 janvier 2017
30
Bonsoir,

Je suis d'accord avec Krimog,

mais pourquoi pas plus simplement:      publicclass Mere<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /??>

      {

            publicstaticreadonlyint Un = 1;

            publicstaticreadonlyint Deux = 2;

            publicstaticreadonlyint Trois = 3;

      }

 

      publicclass Fille : Mere

      {

            publicstaticreadonlyint Quatre = 4;

            publicstaticreadonlyint Cinq = 5;

      }

?
C# is amazing, enjoy it!
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
44
J'y ai pensé à la base, mais c'est pour éviter les choix non valides.

private void MaMethode(int val);
=> MaMethode(Mere.Un); // ça marche
=> MaMethode(Fille.Deux); // ça marche
=> MaMethode(50); // ça marche alors que ça ne devrait pas

avec ma méthode :
private void MaMethode(Mere val);
=> MaMethode(Mere.Un); // ça marche
> MaMethode(Fille.Deux); // > Impossible de caster un Fille en Mere (enfin je crois, pas testé)
> MaMethode(50); // > Impossible de caster un int en Mere.

private void MaMethode(Fille val);

=> MaMethode(Mere.Un); // ça marche

=> MaMethode(Fille.Deux); // ça marche

> MaMethode(50); // > Impossible de caster un int en Mere

voilà la raison ;)

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
44
Ah mince, c'est dans l'autre sens que ça ne marche pas :

private void MaMethode(Mere val);
=> MaMethode(Fille.Deux); // marche

private void MaMethode(Fille val);
=> MaMethode(Mere.Un); // marche pas

Le fait que ça ne marche pas pour la deuxième solution n'est pas problématique
Cependant, le fait que ça marche pour la première l'est plus...
A part en faisant une vérification de type de val dans MaMethode, je ne vois pas comment éviter ça...
Ouvert aux suggestions ;)

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
54
En C#, les values-type ne peuvent pas être dérivés.
Cela dit, il faut plutôt se poser la question s'il n'y a pas un problème de conception là derrière ?

<hr />
-Blog-
-Site Perso-
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
humm... comme le dit bidou, il n'est pas possible de dériver des types valeurs en .net.

Par contre, tu peux résoudre ton problème en utilisant une struct plutot qu'une classe. Un bon exemple : étudie la façon dont sont implémentées les struct Color et Colors.

Enfin, il est important de comprendre qu'une enum n'évite pas de passer n'importe quelle valeur à une méthode.
Par exemple le code suivant est parfaitement valable (et compile) :

public enum MonEnum {
Zero : 0,
Un,
Deux,
Trois
}

public void MaMethod(MonEnum value) { ... }

MaMethod((MonEnum)50);
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
44
A ceci près que là tu vois que tu utilises un comportement potentiellement risqué, puisque tu es obligé de faire un cast alors qu'un gentil enum est fait pour toi.

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
54
Il n'y a rien de risqué, le cast est toujours valide.

<hr />
-Blog-
-Site Perso-
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
Biensûr que c'est risqué... mais ça marche !

En fait, le problème avec la réponse de Robert33 que tu as validé c'est qu'elle n'évite pas de passer n'importe quelle valeur... puisqu'en réalité ta méthode a besoin d'un _int_.
C'est pourquoi je t'ai conseillé de regarder le fonctionnement de Color.

struct Color {
public byte A;
public byte R;
public byte G;
public byte B;

public Color (byte a, byte r, byte g, byte b) {
this.A = a;
this.R = r;
this.G = g;
this.B = b;
}

public static Color Red { get { return new Color(255,255,0,0); } }
public static Color Blue{ get { return new Color(255,0,0,255); } }
public static Color Green{ get { return new Color(255,0,255,0); } }
}

Donc, s'il l'on applique à ton exemple, ça donne :

public struct Mere {
public int MaValeur;
public Mere(int maValeur) {
this.MaValeur = maValeur;
}

public static Un { get { return new Mere(1); } }
public static Deux { get { return new Mere(2); } }
public static Trois { get { return new Mere(3); } }
}

public struct Fille : Mere {
public Fille(int valeur) : base(valeur) {}

public static Quatre { get { return new Fille(4); } }
public static Cinq{ get { return new Fille(5); } }
}
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
44
@Bidou : "Il n'y a rien de risqué, le cast est toujours valide." => Le cast est parfaitement valide, mais ce n'est pas pour autant que ça ne peut pas être à risque. Exemple :
enum monEnum
{
    machin = 1,
    truc = 2
}

int maMethode(monEnum m)
{
    return 10/(int)m;
}

=> si tu appelles maMethode((monEnum)0); il ne faudra pas te plaindre si ça plante. Et dans ce cas précis, je critiquerais plutôt la personne pour avoir appelé maMethode avec 0 que pour ne pas avoir blindé la maMethode. (Il est obligatoire de blinder l'interface utilisateur, car, de base, l'utilisateur est con, rappelons-le, mais un programmeur qui fait un cast pour pouvoir placer la valeur qu'il souhaite, selon moi, cherche un peu la merde :-) (et s'il met une variable à la place de l'entier, il peut très bien blinder l'appel à la méthode)).

@Sebmafate :
Tout d'abord, si mes souvenirs sont corrects, une structure ne peut pas hériter de quoique ce soit. A la limite, elle peut juste implémenter des interfaces. (De plus, tu as oublié de préciser le type des valeurs de retour de tes propriétés ;-), enfin, c'est pas le problème).
Ta méthode marche (à 2-3 détails près), cependant, elle ne blinde pas ni ne "décourage" le programmeur d'utiliser des valeurs imprévues. Sur ce point, mon code n'ayant pas de constructeur et une propriété en lecture seule, il ne permet pas de mettre n'importe quoi.
Cependant, il reste un défaut à ma méthode, c'est que l'on peut donner une valeur de fille lorsqu'on demande une mère (c'est d'ailleurs la raison de base de mon autre post).

Ceci dit, ce n'est que mon point de vue, qui n'est pas forcément le meilleur.

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
54
Pas vraiment, c'est de la responsabilité de la méthode qui prend l'enum en paramètre en principe.
Pour les guidlines des enums, voire: http://blogs.codes-sources.com/coq/archive/2009/02/20/une-num-ration-enum-en-c-num-re-mais-ne-donne-pas-de-garantie.aspx.

<hr />
-Blog-
-Site Perso-
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
44
C'est une question de point de vue.
Je suis d'accord que c'est toujours mieux de blinder, mais si on demande de manière très explicite à une programmeur de mettre un nombre en 1 et 10 et qu'il s'amuse à mettre 42...

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
54
Bof pas tellement, je suis persuadé que si tu avais un int à la place de l'enum, tu aurais fait quelques choses comme:

if(val == 0) throw new ArgumentException(...)
else
{
   double d = x/val
}

Etant donné que l'enum dérive de int..........

<hr />
-Blog-
-Site Perso-
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
44
C'est clair. J'aurais blindé si c'était un int. Cependant, je vois pas ce qui pourrait pousser quelqu'un à appeler la fonction avec une valeur qu'on ne propose pas. (L'esprit de contradiction ?)
Avez-vous un travail ? _ _ _ (forcément, "ça dépend" ça dépasse ^^) (je ne suis pas sûr de l'exactitude de la partie question de la citation cependant). Au final ça revient un peu au même.

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
44
Ah, j'ai retrouvé la citation exacte : "Exercez-vous une profession ? _ _ _"

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
54
Et c'est bien là le problème qu'on soulève avec un enum...
Il n'est pas limité aux valeurs qu'il propose! C'est à dire que de mettre une autre valeur que celle de l'enum ne soulève aucune exception.
C'est la porte ouverte à toutes les failles que de ne pas faire les tests appropriés (sous prétexte qu'il peut seulement prendre logiquement un set de valeur prédéfini).
Et c'est justement la source de bons nombres de failles: mettre des valeurs qui n'était pas prévu par le programmeur......

<hr />
-Blog-
-Site Perso-