2011-09-09 1 views
3

Je cherche à créer un modèle d'énumération de style Java pour C# qui prend également en charge l'héritage. J'ai des problèmes avec le rendement du rendement. Plus précisément, renvoyer les valeurs de BaseEnum à partir de la propriété Valeurs de ChildEnum.C#: Construction d'énumérations de style java avec héritage

public class BaseEnum { 
    public static readonly BaseEnum A = new BaseEnum("A"); 
    public static readonly BaseEnum B = new BaseEnum("B"); 
    public static readonly BaseEnum C = new BaseEnum("C"); 

    public static IEnumerable<BaseEnum> Values { 
     get { 
      yield return A; 
      yield return B; 
      yield return C; 
     } 
    } 

    public readonly String Name; 

    protected BaseEnum(String name) { 
     this.Name = name; 
    } 

    public static void TestMain() { 
     Console.WriteLine("BaseEnum, should print (A,B,C):"); 
     foreach(BaseEnum e in BaseEnum.Values) { 
      Console.WriteLine(e.Name); 
     } 
     Console.WriteLine("BaseEnum in ChildEnum, should print (A,B,C,D,E):"); 
     foreach(BaseEnum e in ChildEnum.Values) { 
      Console.WriteLine(e.Name); 
     } 
     Console.WriteLine("ChildEnum in ChildEnum, should print (D,E):"); 
     foreach(ChildEnum e in ChildEnum.Values) { 
      Console.WriteLine(e.Name); 
     } 
    } 
} 

class ChildEnum : BaseEnum { 
    public static readonly ChildEnum D = new ChildEnum("D"); 
    public static readonly ChildEnum E = new ChildEnum("E"); 

    new public static IEnumerable<BaseEnum> Values { 
     get { 
      // yield return BaseEnum.Values; // This is what I want to do. It gives the error message below: 
      // Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<Abra.Workshop.EnumABC>' 
      // to 'Abra.Workshop.EnumABC'. An explicit conversion exists (are you missing a cast?) 

      yield return D; 
      yield return E; 
     } 
    } 

    public ChildEnum(string name) 
     : base(name) { 
    } 
} 

/* Output! 
BaseEnum, should print (A,B,C): 
A 
B 
C 
BaseEnum in ChildEnum, should print (A,B,C,D,E): 
D 
E 
ChildEnum in ChildEnum, should print (D,E): 
D 
E 
*/ 
+0

J'ai pu obtenir le résultat souhaité en utilisant la réflexion dans le bloc Valeurs. – Jim

Répondre

1

Utilisez

foreach (var b in BaseEnum.Values) 
    yield return b; 

Vous devez déballer BaseEnum.Values ​​en éléments individuels.

Ou le remplacer par une expression LINQ: -

return BaseEnum.Values.Concat(new[]{ D, E }); 
+0

En utilisant la réflexion, j'ai pu éviter d'avoir à énumérer chaque item enum. – Jim

1
class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("BaseEnum, should print (A,B,C):"); 
     foreach (BaseEnum e in BaseEnum.Values) 
     { 
      Console.WriteLine(e.Name); 
     } 
     Console.WriteLine("BaseEnum in ChildEnum, should print (A,B,C,D,E):"); 
     foreach (BaseEnum e in ChildEnum.Values) 
     { 
      Console.WriteLine(e.Name); 
     } 
     Console.WriteLine("ChildEnum in ChildEnum, should print (D,E):"); 
     foreach (ChildEnum e in ChildEnum.Values.Where(d => d.GetType() == typeof(ChildEnum))) 
     { 
      Console.WriteLine(e.Name); 
     } 
    } 
} 

public class BaseEnum 
{ 
    public static readonly BaseEnum A = new BaseEnum("A"); 
    public static readonly BaseEnum B = new BaseEnum("B"); 
    public static readonly BaseEnum C = new BaseEnum("C"); 

    public static IEnumerable<BaseEnum> Values 
    { 
     get 
     { 
      yield return A; 
      yield return B; 
      yield return C; 
     } 
    } 

    public readonly String Name; 

    protected BaseEnum(String name) 
    { 
     this.Name = name; 
    } 
} 

public class ChildEnum : BaseEnum 
{ 
    public static readonly ChildEnum D = new ChildEnum("D"); 
    public static readonly ChildEnum E = new ChildEnum("E"); 

    new public static IEnumerable<BaseEnum> Values 
    { 
     get 
     { 
      foreach (var baseEnum in BaseEnum.Values) 
       yield return baseEnum; 

      yield return D; 
      yield return E; 
     } 
    } 

    public ChildEnum(string name) 
     : base(name) 
    { 
    } 
} 
0

est ici une version qui élimine la nécessité d'avoir le new public static méchant recenseur.

Cela change la structure d'héritage pour que cela fonctionne. Je pensais que je l'avais pensé comme une alternative.

public class BaseEnum<E> where E : BaseEnum<E>, new() 
{ 
    public static readonly E A = new E() { Name = "A" }; 
    public static readonly E B = new E() { Name = "B" }; 
    public static readonly E C = new E() { Name = "C" }; 

    public string Name { get; protected set; } 

    protected static IEnumerable<E> InternalValues 
    { 
     get 
     { 
      yield return A; 
      yield return B; 
      yield return C; 
     } 
    } 
} 

public class BaseEnum : BaseEnum<BaseEnum> 
{ 
    public static IEnumerable<BaseEnum> Values 
    { 
     get { foreach (var x in InternalValues) yield return x; } 
    } 
} 

public class ChildEnum : BaseEnum<ChildEnum> 
{ 
    public static readonly ChildEnum D = new ChildEnum() { Name = "D" }; 
    public static readonly ChildEnum E = new ChildEnum() { Name = "E" }; 

    public static IEnumerable<ChildEnum> Values 
    { 
     get 
     { 
      foreach (var x in InternalValues) yield return x; 
      yield return D; 
      yield return E; 
     } 
    } 
} 

Il ne nécessite aussi un défaut constructeur public, mais grâce au compositeur protégé sur le seul code propriété Name en cours d'exécution dans la hiérarchie d'héritage peut définir le nom, donc si une instance est apparue sans nom vous savez que quelqu'un fait quelque chose de mal.