我问过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#必须使用反射来获取枚举数?为什么在编译期间不能这样做?
答案 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#必须使用反射来获取枚举数?为什么 在编译期间不能这样做吗?
它可以这样做。但是你会遇到上面的问题。编译时计算的值可能会变得不正确。