14

列挙型に問題があります

基本クラスまたはインターフェイスで列挙型を作成する必要があります (ただし、空のもの)

class Base 
{
   public enum Test;
   // ???
}

そして、いくつかの親クラスで異なる列挙型を作成した後

class Parent1
{
   public enum Test {A, B, C};
}

class Parent2
{
   public enum Test {J, H, K};
}

そして今、私は列挙型を使用しなければならないときにメソッドを持つ次のクラスを持っています

class Test<T>
{
   public void Foo(Test enum)
   {
      int value = (int) enum;
      // ...
   }
}

そのようなことをする方法はありますか?

そうでない場合は、すべてのクラスで静的 int を使用する必要があります...

class Parent1
{
   public static int A = 0;
   public static int B = 5;
   public static int C = 7;
}

class Parent2
{
   public static int J = 1;
   public static int H = 3;
   public static int K = 6;
}

class Test<T>
{
   public void Foo(int enum)
   {
      int value = enum;
      // ...
   }
}

コードの見た目は悪くありません...一部のクラスでは、〜20以上の変数を使用する必要があります

4

10 に答える 10

28

尋ねられた質問に答えたり、おしゃべりをしたりするのではなく、なぜ何かが必要なのかについて議論している人をよく見かけます.実際に答えを知っています。尋ねられていない質問に答えても、何の役にも立たないよ。

手元のトピックに戻ると、今朝まさに上記のシナリオに当てはまりました。インターフェイスまたは基本クラスで Enum を定義し、同じ名前の Enum を再定義できると便利な理由を理解できます。ベースまたはインターフェイスのいずれかから派生するクラスで。このような設計の用途の 1 つは、オブジェクト リレーショナル マッピングとコントロール バインディングです。次のように、派生クラスのどのプロパティがどのタイプのコントロールにバインド可能かを記述する列挙型のセットがある場合があります。

    public enum WebControlTextBoxProperties { }

    public enum WebControlLabelProperties { }

...等々。

関連する継承が有効になるまで、特定の派生クラスにどのプロパティが存在するか正確にはわかりませんが、ベースまたはインターフェイスで上記の列挙型を消費する一貫したメソッドが必要な場合があるため、これは完全に有効な設計です。列挙型がベース/インターフェースに存在することを定義できると期待するが、派生クラスの特定のコンテキストに含まれるメンバーを正確に定義します。

VB と同様に C# でもこれが可能になることを切に願っています。これは非常に便利な機能だからです。

于 2010-10-19T08:39:15.790 に答える
25

抽象列挙型 (サブクラスで異なる実装を持つことができる) のようなものはありませんが、ジェネリックはオプションの場合があります。

class Base<T> where T : struct {
    private T value;
    public void Foo(T value) {
        this.value = value;
    }
}
class Parent1 : Base<Parent1.Enum1> {
    public enum Enum1 {A, B, C};
}
class Parent2 : Base<Parent2.Enum2> {
    public enum Enum2 { J, H, K };
}

唯一の問題は、列挙型のみが使用可能であることを強制しないことです。ただし、実行時にこれを行うことができます。たとえば、型初期化子で:

static Base() {
    if (!typeof(T).IsEnum) throw new InvalidOperationException(
         typeof(T).Name + " is not an enum");
}
于 2009-06-23T09:56:32.677 に答える
4

基本クラスで列挙型を宣言し、派生クラスごとに値を変更できる必要があります。

class MyClass
{
    public enum TestEnum { }

    public MyClass()
    {
    }
}

class MyDerivedClass
{
    public enum TestEnum { value1, value2, value3 }

    public MyDerivedClass()
    {
    }
}

MyDervied クラスは TestEnum.value1、TestEnum.value2、TestEnum.value3 にアクセスできますが、MyClass は型にしかアクセスできません。

ただし、個人的には、これを行う利点がわかりません。基本クラスで列挙型のすべての値を宣言し、クラスごとに必要なものだけを使用します。

ジェームズ。

于 2009-06-23T09:59:40.893 に答える
1

基本クラスで列挙型を定義できないのはなぜですか:

class Base 
{
   public enum Test {A, B, C, J, H, K};
}

派生クラスで enum の関連メンバーのみを使用しますか?

于 2009-06-23T09:57:18.200 に答える
1

いいえ、できません。

多くの列挙型は、多くの場合、設計上の問題を示していることに注意してください (たとえば、多くのスイッチ構造)。このリンクをチェックして、これをリファクタリングする方法の例を確認してください: Replace conditional with polymorphism .

于 2009-06-23T09:57:58.090 に答える
0

いいえ、インターフェイスで静的なものを強制する方法はありません。

おそらく、設計を再考する必要があります。

于 2009-06-23T09:54:04.850 に答える
0

私は仕事をしているので、詳しく説明することはできませんが、これはある程度可能です。以下のコードの欠点は、TextBoxProperties や MyCustomTextBoxProperties などの列挙型を連結できないことです。

これがコードです。

    public enum Test
    {

    }

    public enum ThisTest
    {
        MyVal1,
        MyVal2,
        MyVal3
    }

    public abstract class MyBase
    {
        public Test MyEnum { get; set; }
    }

    public class MyDerived : MyBase
    {
        public new ThisTest MyEnum { get; set; }
    }
于 2012-12-20T13:59:41.793 に答える
0

@Marc Gravellの受け入れられた答えが好きです。私はスタックオーバーフローの初心者なので、コメントすることはできません。しかし、特にフラグ属性を使用してビット単位のフラグテスト操作を実行する場合は、列挙型の基になるタイプもチェックすると便利であることを追加したいと思います...

if ( !typeof(T).IsEnum || typeof(int) != Enum.GetUnderlyingType(typeof(T)) )
{
     throw new InvalidOperationException( typeof(T).Name + " is not an enum");
}
于 2017-05-13T19:22:33.393 に答える