2009-06-23 135 views
12

我有枚舉問題在接口/基類中的C#枚舉?

我需要做的基類或接口(但空單)

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

有沒有辦法做到這樣的事情?

如果不是我在每類中使用靜態整數...

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

I'T很糟糕的代碼......在某些類我必須使用〜20個+變量

+2

也許這是一個好主意,重新檢查你的假設 - 你爲什麼需要這個?試着重新解釋這個問題,以包括你實際嘗試完成的事情,而不是專注於你接近問題的方式。 :) – Rytmis 2009-06-23 09:55:13

+0

什麼是你想用它,真的嗎?具有相同枚舉的不同實現似乎與枚舉的目的是相反的...... – Guffa 2009-06-23 09:57:07

+3

@Groo:不,它將值添加到枚舉中,這是一個具有對象特定值的抽象枚舉,但實現一個一致的界面,所以它的成員可以被傳遞。馬克的回答是我見過的最好的答案。 – 2011-09-13 03:03:35

回答

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"); 
} 
+0

以及其最佳的解決方案,我不能使用的只有一件事: 抽象公共類DB 其中T:基本,INTERF,新的() 我明白爲什麼,我必須使用靜態INT的不枚舉然後 – kaem 2009-06-23 10:33:41

+0

「有不是抽象枚舉(可以在子類中有不同的實現) - 但泛型可能是一個選項:「 - 錯誤! System.Enum是所有枚舉的抽象基礎 – 2013-05-24 00:47:57

+0

@SimonBridge請參閱問題的上下文 – 2013-05-24 06:21:31

0

不,在界面中無法強制任何靜態內容。

也許你需要重新考慮你的設計。

0

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

並只使用派生類中的枚舉的相關成員?

1

不,不能這樣做。

請注意,許多枚舉通常表示設計有問題(例如,許多開關結構)。查看此鏈接以查看如何重構此示例:Replace conditional with polymorphism

3

你應該能夠在基類中聲明枚舉,然後更改每個派生類的值即

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只能訪問該類型。

但是,我個人並沒有看到這樣做的好處,我將在基類中聲明枚舉的所有值,並僅使用每類所需的值。

James。

27

令人驚訝我怎麼經常發現人們爭論爲什麼東西是必需的,而不是回答這個問題詢問或保持schtum - 無論其是不是浪費時間質疑更有幫助,爲什麼給定的調查已經取得了而不是被調查者實際知道的答案。回答沒有問過的問題絕對沒有幫助,好吧?!

回到手頭的話題,我已經在上午完成了上述場景,並且可以理解爲什麼能夠在接口或基類中定義枚舉是有用的,然後重新定義在源自基礎或接口的類中的同名Enum。這種設計的一個用處在於對象關係映射和控制綁定。您可能有一組枚舉說明派生類的哪些屬性可以綁定到哪些類型的控件,例如:

public enum WebControlTextBoxProperties { } 

    public enum WebControlLabelProperties { } 

...等等。

既然您不知道給定的派生類將存在哪些屬性,直到相關的繼承生效,但由於您可能還希望在您的基礎或接口中使用上述枚舉的一致方法,所以它是完美,有效的設計,以期望能夠定義枚舉將在基地/界面存在,但確切定義它在任何派生類特定的上下文是什麼會員

我真的希望這是可能在C#中,因爲它是在VB,因爲它會是一個非常有用的功能。

0

我在工作,所以還不能完全闡明,但是這是可能的一個點。下面的代碼的缺點是你不能鏈接在一起,如TextBoxProperties和MyCustomTextBoxProperties:TextboxProperties

這是代碼。

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

YOU CAN 摘要:枚舉!

爲什麼人們堅持聲稱事情是不可能的,不檢查什麼嗎?

肯定的是,.NET文檔是對這個有點模糊,但System.Enum類,是一個枚舉的抽象。您可以使用System.Enum爲只接受枚舉值的變量,你可以通過這個類來訪問枚舉的名稱或值類型的值。

例如:

 // abstracted enumeration value 
     Enum abstractEnum = null; 

     // set to the Console-Color enumeration value "Blue"; 
     abstractEnum = System.ConsoleColor.Blue; 

     // the defined value of "ConsoleColor.Blue" is "9": 
     // you can get the value via the ToObject method: 
     Console.WriteLine((int)Enum.ToObject(abstractEnum.GetType(), abstractEnum)); 

     // or via the GetHashCode() method: 
     Console.WriteLine(abstractEnum.GetHashCode()); 

     // the name can also be acessed: 
     Console.WriteLine(Enum.GetName(abstractEnum.GetType(), abstractEnum)); 

從上面的代碼的輸出:

0

我喜歡@Marc Gravell的接受的答案。 因爲我是一個計算器,新手我不允許發表評論。但我想補充,它是有用的同時檢查枚舉的基本類型 - 特別是如果你使用標誌屬性和預製件逐位標誌測試操作...

if (!typeof(T).IsEnum || typeof(int) != Enum.GetUnderlyingType(typeof(T))) 
{ 
    throw new InvalidOperationException(typeof(T).Name + " is not an enum"); 
} 
0

這裏有一個解決方案這對我的作品:

在父類

,聲明場如int,不作爲枚舉:

protected int state; 

所以父類仍然可以使用這個值作爲一個int,以提供系列化,將此值反序列化到磁盤。

那麼,是誰覆蓋類可以做到這一點:

enum states{ 
    state1, state2 
} 

this.state = state1.toInt(); 

,並且可以訪問這樣的實際值:

... 
if (this.state == states.state1.toInt()){ 
     ... 
} 
else{ 
    ... 
} 

其中toInt()的靜態類的定義如下:

public static class Utils 
{ 

    public static int toInt(this state s) 
    { 
     return (int)s; 
    } 
}