是否可以以编程方式检查枚举是否设置了初始化器?

时间:2013-04-02 20:55:13

标签: .net enums initializer

我想将一个枚举作为一个int,但只有当它有一个初始化程序时才应用它 - 所以我知道该值是明确定义的,而不仅仅是默认值。这是因为我使用枚举来表示具有已定义的int代码的映射。有没有办法用枚举来做这个,或者我将不得不使用像字典一样的其他东西?

这是一个例子 - 我有以下映射:

苹果= 1, 香蕉= 2, 梨= 4, 菠萝= 7

我想确保如果枚举是

public enum Fruit
{
Apples,
Bananas,
Pears,
Pineapples
}

它不会尝试获取int值,因为枚举中的值1对应于Bananas,而不是Apples,就像它应该的那样。如果我需要更清楚,请告诉我。

更新

我使用可以为空的枚举来检查值是否已设置(或未知元素),但这不是我在这里要求的。我不认为我做得很好,所以我会再试一次。

我希望能够获得一个我一无所知的枚举,获取底层的int然后用它做一些事情。我唯一关心的是枚举被初始化,因为它告诉我它已经定义了实际的代码。我不介意它是否为空。这是我检查的事情之一。但是如果它不是null,我想确保明确定义int代码。代码0是完全可以接受的 - 即使它意味着它是未定义的 - 只要这是原始映射指定的。

另一个更新:

我从Microsoft documentation获得了“初始化”这个术语,我认为这引起了混乱。我的意思是一个枚举,它具有明确定义的底层int的值。即,

public enum MyEnum
{
One = 1,
Two = 2,
Three = 3
}

而不是那个。即,

public enum MyEnum
{
One,
Two,
Three
}

我认为这也引起了混淆,我将其称为具有默认值集,这很容易与默认情况下设置了第一个元素的非可空枚举混淆。

我使用它的方式是我有一个方法,它使用反射来获取具有某些自定义属性的属性的值。出于我的目的,我只想从枚举中获取明确定义代码的值。否则我不能假设int值有任何商业意义。

3 个答案:

答案 0 :(得分:1)

在IL级别,枚举只是一个整数(除非它是盒装的);你无法从明确的0中分辨出隐含的0Nullable<SomeType>(又名SomeType?)可能是一个可行的想法。除此之外:你必须提出一些零和默认的本地定义。

答案 1 :(得分:0)

枚举实际上是下面的序数值类型,因此它们不能是null,并且无法应用类似的解决方案。

最佳解决方案是添加对应于值0的枚举条目。例如

public enum Fruit
{
    Unknown = 0,
    Apples,
    Bananas,
    Pears,
    Pineapples
}

Fruit someFruit;
if (someFruit == Fruit.Unknown)
    Console.WriteLine("fruit is not initialized");
else
    Console.WriteLine("fruit is initialized");

另一种接近它的方法是将值包装到Nullable中。这样您就可以将变量设置为null

public enum Fruit
{
    Apples,
    Bananas,
    Pears,
    Pineapples
}

Fruit? someFruit;
if (!someFruit.HasValue)
    Console.WriteLine("fruit is not initialized");
else
    Console.WriteLine("fruit is initialized");

答案 2 :(得分:0)

(非可空)枚举值始终是有效整数。因此,可以获得枚举中任何常量都不使用的值:

Fruit myFruit = (Fruit)12345;    // Some random integer

反过来说:你可以总是获取任何枚举的整数值,无论其值是否定义为常量。

Fruit myFruit = (Fruit)12345;
int myFruitInt = (int)myFruit;

因此,如果您想确保枚举的值是enum定义中定义的值之一,您可以使用Enum.IsDefined method,如下所示:

Fruit myFruit;
bool isDefined;

myFruit = Fruit.Bananas;
isDefined = Enum.IsDefined(typeof(Fruit), myFruit); // true, Bananas

myFruit = (Fruit)1;
isDefined = Enum.IsDefined(typeof(Fruit), myFruit); // true, Bananas

myFruit = Fruit.Bananas | Fruit.Pineapples;
isDefined = Enum.IsDefined(typeof(Fruit), myFruit); // false

myFruit = (Fruit)12345;
isDefined = Enum.IsDefined(typeof(Fruit), myFruit); // false

当然,您可以在方法中添加Type,而不仅仅是typeof(Fruit)


您谈论初始化的枚举。哪有这回事。枚举可以具有任何整数值。值类型(包括枚举)的默认值为0.但完全可能(甚至建议)存在值为0的枚举常量(通常命名为NoneUnknown或{ {1}})。因此,以下语义完全相同

Default

你无法在运行时区分,因为没有区别。


显然private Fruit myFruit; private Fruit myFruit = (Fruit)0; private Fruit myFruit = Fruit.Unknown; 上的MSDN文档声明:

  

默认情况下,第一个枚举数的值为0,每个连续枚举数的值增加1.例如,在下面的枚举中,Sat为0,Sun为1,Mon为2,依此类推。

enum
     

枚举器可以使用初始值设定项覆盖默认值,如以下示例所示。

enum Days {Sat, Sun, Mon, Tue, Wed, Thu, Fri};
     

在此枚举中,强制元素序列从1开始而不是0.但是,建议包括值为0的常量。

我不确定文档是否会调用这些初始化程序,因为没有任何内容初始化。它只是让您的生活更轻松的语法。你也可以指定等价物:

enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};

也许它们意味着enum Days {Sat=1, Sun=2, Mon=3, Tue=4, Wed=5, Thu=6, Fri=7}; 初始值,编译器将从中开始计数,以便为其后面的枚举常量分配一个常量整数值。例如:

1

相当于:

enum Days {Sat, Sun=2, Mon, Tue=10, Wed, Thu, Fri=11};

同样,没有任何内容被初始化