2010-12-08 10 views
2

私はユーザーフレンドリな識別子と任意の関連値で列挙型を作成できるようにするカスタム列挙型クラスを取得しようとしています。これまでのところ良い:静的フィールドでの不思議な動作

public class EnumBase<T, E> 
    where E : class 
{ 
    private static readonly List<E> list = new List<E>(); 

    private string text; 
    private T value; 

    public string Text { get { return text; } } 
    public T Value { get { return value; } } 

    public EnumBase(string text, T value) 
    { 
     this.text = text; 
     this.value = value; 
     list.Add(this as E); 
    } 

    protected static IEnumerable<E> ItemList 
    { 
     get { return list; } 
    } 
} 

public class Zahlungsart : EnumBase<int, Zahlungsart> 
{ 
    public static readonly Zahlungsart Erlagsschein = new Zahlungsart("Erlagsschein", 0); 
    public static readonly Zahlungsart Lastschrift = new Zahlungsart("Lastschrift", 1); 

    private Zahlungsart(string text, int value) : base(text, value) { } 
    public static new IEnumerable<Zahlungsart> ItemList { get { return EnumBase<int, Zahlungsart>.ItemList; } } 
} 

そして今、私の問題:

Console.WriteLine(Zahlungsart.ItemList.Count()); 

次の文は私に0を与え、問題はbeforefieldinitする予定である代わりに2の、私は思います。私は静的なフィールドを強制的にロードする特定の列挙型のメソッドを呼び出すことでこれを回避できますが、これは最善の解決策ではありません。

ヒント:ここでは、何らかの[UserfriendlyName()]属性を列挙しないでください。私は既にそれらを知っています。

EDIT ありがとう、ハンス。私は間違ったジェネリックスペシャライゼーションを呼び、自分のコードに誤字がありました。

私の質問は、各サブクラスでItemListの再定義を取り除くことができますが、静的フィールドを初期化する必要があるようです。

+0

同じコードを実行すると、出力として「2」が得られます。 – cdhowie

答えて

1

あなたのコードは問題を再現しません。あなたはこのようにプロパティを変更した場合しかし、あなたはREPROを取得します:

public new static IEnumerable<Zahlungsart> ItemList { 
     get { return EnumBase<uint, Zahlungsart>.ItemList; } // Note: uint instead of int 
    } 

がジェネリック型から生成されたすべての具象クラスは、独自の静的フィールドを持つことになりますので注意してください、彼らはないが共有あります。

+0

あなたは正しいです、私は実際に働いていたものを投稿したコードの周りにそんなに疲労しています:) – codymanix

+0

各サブクラスでItemListの再定義を回避できますか?それがなければ、スタティックctorは呼び出されません。これは、問題の派生クラスの最初の静的メンバーにアクセスするまで、countが0であることを意味します。 – codymanix

+0

できません。これは基本的な動作です。静的メンバーのタイプが異なるため、共有はできません。あなたはこれを再考する必要があります。 –

2

「静的コンストラクタ」の使用はどうですか?

public class Zahlungsart : EnumBase<int, Zahlungsart> 
{ 
    public static readonly Zahlungsart Erlagsschein; 
    public static readonly Zahlungsart Lastschrift; 

    static Zahlungsart() 
    { 
     Erlagsschein = new Zahlungsart("Erlagsschein", 0); 
     Lastschrift = new Zahlungsart("Lastschrift", 1); 
    } 

    private Zahlungsart(string text, int value) : base(text, value) { } 
    public static new IEnumerable<Zahlungsart> ItemList { get { return EnumBase<int, Zahlungsart>.ItemList; } } 
} 
+0

コンパイラはすでに、自動的にcctorを生成して読み取り専用メンバを初期化します。これは何の違いもありません。 –

+0

@ハンス、それはできます。静的コンストラクタは "beforefieldinit"フラグを削除し、型が最初に使用されたときにすべての静的フィールドが実行されるようにします。静的コンストラクタのない型は "beforefieldinit"としてマークされ、静的フィールドは最初に参照される前に初期化されることが保証されますが、他のコードがその型で実行される前に初期化されるという保証はありません。 http://www.yoda.arachsys.com/csharp/beforefieldinit.html – sisve

+0

なぜ間違った答えが得られるのですか? – codymanix

関連する問題