2011-09-09 9 views
3

C#用のJavaスタイルの列挙型パターンを作成して継承もサポートしたいと考えています。私は利回りの返品に問題があります。具体的には、ChildEnumのValuesプロパティからBaseEnumの値を返します。C#:継承を使用してJavaスタイルの列挙型を構築する

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

値取得ブロックでリフレクションを使用して、私が望む結果を得ることができました。 – Jim

答えて

1

あなたは、個々の要素にBaseEnum.Valuesのラップを解除する必要が使用

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

またはLINQ式に置き換えます -

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

リフレクションを使用して、私は個々の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

ここで厄介なnew public static列挙子を持つ必要性を廃止したバージョンです。

継承構造が変更されて動作します。私はそれを代替案と考えていたと思った。

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; 
     } 
    } 
} 

それはデフォルトのパブリックコンストラクタをも必要としますが、インスタンスが誰かということ、あなたが知っている名前なしで現れので、もし継承階層で動作しているName財産上の保護されたセッターのおかげで唯一のコードは、名前を設定することができます何かが間違っている。

関連する問題