2009-02-23 118 views

回答

46

枚舉應該是類型安全的。我認爲他們並沒有讓它們含蓄地拒絕其他用途。雖然框架允許你爲它們分配一個不變的值,但你應該重新考慮你的意圖。如果您主要使用枚舉來存儲常量值,請考慮使用靜態類:

public static class ReturnValue 
{ 
    public const int Success = 0; 
    public const int FailReason1 = 1; 
    public const int FailReason2 = 2; 
    //Etc... 
} 

可讓您執行此操作。

public static int main(string[] args){ 
    return ReturnValue.Success; 
} 

編輯

當你要提供值枚舉是當你想將它們結合起來。見下面的例子:

[Flags] // indicates bitwise operations occur on this enum 
public enum DaysOfWeek : byte // byte type to limit size 
{ 
    Sunday = 1, 
    Monday = 2, 
    Tuesday = 4, 
    Wednesday = 8, 
    Thursday = 16, 
    Friday = 32, 
    Saturday = 64, 
    Weekend = Sunday | Saturday, 
    Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday 
} 

這個枚舉然後可以通過使用按位數學被消耗。有關某些應用程序,請參閱以下示例

public static class DaysOfWeekEvaluator 
{ 
    public static bool IsWeekends(DaysOfWeek days) 
    { 
     return (days & DaysOfWeek.Weekend) == DaysOfWeek.Weekend; 
    } 

    public static bool IsAllWeekdays(DaysOfWeek days) 
    { 
     return (days & DaysOfWeek.Weekdays) == DaysOfWeek.Weekdays; 
    } 

    public static bool HasWeekdays(DaysOfWeek days) 
    { 
     return ((int) (days & DaysOfWeek.Weekdays)) > 0; 
    } 

    public static bool HasWeekendDays(DaysOfWeek days) 
    { 
     return ((int) (days & DaysOfWeek.Weekend)) > 0; 
    } 
} 
+0

工程就像一個魅力,謝謝!奇怪的是你可以定義一個枚舉:「public enum MyEnum:int {...}」,並且它的值不能隱式轉換。那裏沒有「泛型枚舉」的概念嗎? - public enum MyEnum - 或者這是完全荒謬的? – Pwninstein 2009-02-23 16:02:23

+0

你可以delcare鍵入你的enum「public enum ReturnValue:int」,它強制值的類型爲int。它仍然不提供隱式轉換。編輯以顯示何時它是一個在枚舉中使用值的好主意。 – 2009-02-23 19:44:05

2

根據規範,枚舉和整數不能隱式轉換(文字0除外,它允許比較測試/賦值/等)。儘管如此,顯式演員仍然是需要的。

+2

(規格13.1.3和ECMA 334v4的13.2.2) – 2009-02-23 15:22:42

+0

這會是很好,如果你可以重寫爲枚舉 – 2011-12-21 14:58:32

+0

等於運算符@克里斯,你可以寫一個擴展方法, 也許。不完全一樣,但... – 2011-12-21 16:47:20

0

不,你不能避免鑄造;至於爲什麼沒有隱含的轉換,我不知道,但沒有。

4

沒有隱式轉換,因爲枚舉不必使用int作爲基礎類型。例如,如果您的枚舉使用uint作爲基礎類型,則不存在從uint到int的隱式轉換。

0

奇怪的是,這不是特定於.NET Framework,而是針對C#。正如其他評論者已經指出的那樣,在C#中這基本上是該語言的一個規範。在VB.NET中也是如此。

查看關於Enums in VB.NET的MSDN參考頁面。請注意,您可以在枚舉聲明時指定枚舉的數據類型。這意味着,如果你確實不想拋棄你的代碼轉換爲(int),你可以在VB.NET中編寫枚舉,將其聲明爲整數,然後使用C#中的Enum。

記得他們告訴我們電腦會讓我們的生活變得如此簡單嗎? :)

0

您可以將此行爲歸因於創建Enumerations ...後面的基本意圖,以創建一組只能根據基礎類型指定(或默認)值的命名常量。

,需要考慮兩個不同的問題,因爲涉及到你的問題:

  1. Enum值不能作爲默認的int來處理,因爲你將能夠提供任何整數且有將不會進行編譯時檢查,以驗證提供的整數實際上是否作爲枚舉值存在。

  2. 鑄造成爲必要的,因爲你正試圖從底層類型,即intbyteYourCustomEnum類型從System.Enum類派生的)主導類型轉換等

4

的c#枚舉是無用的。

您可以避免從您的類型轉換,並通過創建一個密封類並提供隱式/顯式轉換運算符來約束可以顯式轉換爲您的類型的值。

  • 提供一個隱式運算符來將您的類型轉換爲泛型int,因此您不必投射。 (int x)=>(x> = 0 & & x < = 2)提供一個顯式操作符,用於將整型轉換爲您的類型,如果整型不符合約束條件,則拋出錯誤。

如果使用這種技術,創建一個通用不可改變的基類如ConstrainedNumber<T>,其具有接受所述約束爲T值和代表一個構造:delegate bool NumberConstraint<T>(T value)。構造函數應該通過約束委託運行該值,如果它不符合約束條件,則拋出異常。基類還應該處理對T的隱式轉換操作,並應通過重載object.Equals(object)和object.GetHashCode()來處理相等性,爲ConstrainedNumber<T>類型定義==和!=運算符,並實現IEquatable<T>IEquatable<ConstrainedNumber<T>>。我還建議爲基類和所有派生類型定義一個拷貝構造函數。然後克隆可以在基類中通過反射檢索拷貝構造函數來實現,但這完全是可選的。你可以自己計算ConstrainedNumber<T>實現,除非我已經將它發佈到了某處的stackoverflow上。

您可以在派生的ConstrainedNumber中提供命名靜態只讀值,以便您可以像訪問枚舉一樣訪問它們。

public sealed class ReturnValue: ConstrainedNumber<int> 
{ 
    public static readonly NumberConstraint<int> constraint = (int x) => (x >= 0 && x < 3); 

    public static readonly ReturnValue Success = new ReturnValue(0); 
    public static readonly ReturnValue FailReason1 = new ReturnValue(1); 
    public static readonly ReturnValue FailReason2 = new ReturnValue(2); 

    private ReturnValue(int value): base(value, constraint) {} 
    private ReturnValue(ReturnValue original): base (original) {} //may be used to support IClonable implementation in base class 
    public static explicit operator ReturnValue(int value) 
    { 
     switch(value) //switching to return an existing instance is more efficient than creating a new one and re-checking the constraint when there is a limited number of allowed values; if the constraint was more generic, such as an even number, then you would instead return a new instance here, and make your constructors public. 
     { 
      case 0: return Success; 
      case 1: return FailReason1; 
      case 2: return FailReason2; 
     } 
     throw new ArgumentException("Value fails to meet the constraint defined for " + typeof(ReturnValue).FullName + ".", "value"); 
    } 

} 

您可以將此技術用於任何約束。例如,一個名爲EvenNumber的類可能有一個約束,如果給定的數字是偶數,則返回true。在這種情況下,你只需要公開你的構造函數,然後簡化你的靜態轉換運算符來返回一個新的EvenNumber,而不是切換到返回一個有限的現有實例。

它可以這樣來使用:

EvenNumber x = (EvenNumber)2; 
EvenNumber y = (EvenNumber)3; //throws exception "Value fails to meet the constraint defined for {namespace}.EvenNumber." A c# enum would stupidly allow such a cast, creating an invalid EvenNumber, breaking the object-oriented model 
int z = x; //implicit conversion, no cast necessary; 
-2

如何使用類的靜態成員?

//enum DocInfos { DocName, DocNumber, DocVersion}; 
public class DocInfos 
{ 
    public static int DocName = 0; 
    public static int DocNumer = 1; 
    public static int DocVersion = 2; 
} 

...

  Doc = new string[DocInfos.DocVersion]; 
      // Treffer 
      Doc[DocInfos.DocName] = TrimB(HTMLLines[lineCounter + 2]) 

...