为什么我不能在编译期间获得枚举数?

时间:2016-04-06 14:08:14

标签: c# reflection enums count compile-time

我问过How can I get the number of enums as a constant?,我发现在编译时我无法得到枚举数,因为C#使用反射来实现这一点。

我读过What is reflection and why is it useful?,所以我对反思有了非常基本的了解。

要获取枚举的计数,我可以使用var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(self.decrease), userInfo: nil, repeats: true) func decrease() { self.secs-=1 self.defaultAction.setValue("Dismiss in \(self.secs)", forKey: "title") } ,这在运行时使用反射时会发生。

我没有看到获取枚举数所需的任何运行时知识,因为据我所知,在运行期间无法更改枚举数。

为什么C#必须使用反射来获取枚举数?为什么在编译期间不能这样做?

3 个答案:

答案 0 :(得分:4)

仅仅因为可以在编译时进行评估并不意味着有人编程编译器这样做。 string.Format("{0:N2}", Math.PI)是另一个例子。

目前获得Enum值的计数的唯一方法是使用反射(Enum.GetNames或类似的东西)。所以它不是一个常量表达式,虽然技术上编译器可以只是在编译时计算表达式并确定结果是什么。

nameof就是一个很好的例子。它在编译时是常量,但是在编译时没有机制来提取结果,直到有人设计,开发,测试,记录和发布该功能。这些都不是免费的,因此这个想法必须争夺有价值的资源(人,时间,金钱)与其他可能更有价值的特征。

因此,如果您认为像enumcount(Item.Type)这样的编译时构造是该语言的一个有价值的补充,那么非常欢迎您在Connect上发布建议并查看它是否适用于该语言功能列表的顶部。

  

但是,我需要将这个数字作为常数,以便我可以在Unity的[Range(int,int)]特征中使用它。

一个非理想的解决方法是定义一个与当前枚举项数相匹配的常量,如果计数不匹配,则在运行时抛出异常:

在枚举旁边定义一个公共常量,对其进行注释,以便开发人员知道更新它:

// Update this value any time the Type enum is updated
public const int TypeCount = 5;
public Enum Type
{
    Bar1,
    Bar2,
    Bar3,
    Bar4,
    Bar5,
}

在您的属性中使用它:

[Range(0, Item.TypeCount)]
public void BlahBlahBlah() {}

并在应用开始时检查:

public static Main()
{
   if(Enum.GetNames(typeof(Item.Type)).Length != Item.TypeCount)
      throw new ApplicationException ("TypeCount and number of Types do not match.\nPlease update TypeCount constant.")
}

答案 1 :(得分:0)

我想简单来说:

枚举是一种“类型定义”,当需要“类型描述符导航”时,.NET使用Reflection。

所以Enums是一个Type和@运行时,如果你想计算你需要用户反思的定义的enums语音。

答案 2 :(得分:0)

  

我没有看到获取枚举数所需的任何运行时知识,   因为据我所知,枚举的数量不能改变   运行时。

以下是您的推理中的错误:是的,在运行时期间无法更改的枚举计数。但是,它可以在运行时之间进行更改:

A.dll - version 1
  public enum Foo { A }

A.dll - version 2
  public enum Foo { Bar, Baz }

将A.dll的版本1替换为版本2.枚举的计数已更改(以及值的名称)。

  

为什么C#必须使用反射来获取枚举数?为什么   在编译期间不能这样做吗?

它可以这样做。但是你会遇到上面的问题。编译时计算的值可能会变得不正确。