为什么我在编译期间无法获得枚举数?

我曾问过如何将枚举数作为一个常量?并且我发现在编译时我无法获得枚举数,因为C#使用反射来完成。

我读了什么是反思,为什么它有用?所以我对反思有一个非常基本的理解。

为了得到枚举数,我可以使用Enum.GetNames(typeof(Item.Type)).Length; ,并且这在运行时使用反射发生。

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

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


仅仅因为可以在编译时对某些东西进行评估并不意味着某人编写了编译器来执行此操作。 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.")
}

我认为简单来说:

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

所以,如果你想计算你需要用户反射的定义的枚举语音,Enums是Type和@运行时间。


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

这是你的推理中的错误:是的,在运行时不能改变枚举数。 但是,它可以在运行时间之间进行更改:

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

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

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

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

它可以这样做。 但是,那么你会遇到上述问题。 编译时计算的值可能会不正确。

链接地址: http://www.djcxy.com/p/91137.html

上一篇: Why can't I get the count of enums during compile time?

下一篇: Export from Google BigQuery into CloudSQL?