2009-02-23 120 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]) 

...