Eig*_*ite 73 c# compiler-construction enums
我今天意外地定义了一个没有值的枚举.像这样的例如:
public enum MyConfusingEnum{}
Run Code Online (Sandbox Code Playgroud)
编译器很高兴让我定义它并成功构建代码.
现在我显然不能使用传统意义上的代码,因为代码,...
var mySadCompiler = MyConfusingEnum;
Run Code Online (Sandbox Code Playgroud)
没有指定值,但有趣的是我很能说,..
var myRoundTheHousesZeroState = Activator.CreateInstance<MyConfusingEnum>();
Run Code Online (Sandbox Code Playgroud)
正如我所提到的,它是一个MyConfusingEnum值为0 的值类型;
我的问题是为什么编译器允许一个空的定义,是否有任何可能有用的场景?
Eri*_*ert 91
首先,您可以更轻松地完成这项工作:
MyConfusingEnum x1 = 0;
MyConfusingEnum x2 = default(MyConfusingEnum);
MyConfusingEnum x3 = new MyConfusingEnum();
MyConfusingEnum x4 = (MyConfusingEnum) 123;
Run Code Online (Sandbox Code Playgroud)
所有上述工作都很好.(您可能会对第一个工作感到惊讶;有关详细信息,请参阅有关隐式枚举转换的规范部分.)
我的问题是为什么编译器允许空定义
我将首先回答你的问题.你还有编译器拒绝吗?
class C {}
interface I {}
struct S {}
Run Code Online (Sandbox Code Playgroud)
为什么或者为什么不?
更直接地不回答你的问题:"为什么这个世界与它没有什么不同?" 问题很难回答.我没有回答那个不可能的问题,而是回答这个问题:"假设制作空的枚举错误已经投给了设计团队;你会如何回应那个音调?" 这个问题仍然是反事实的,但至少我能回答这个问题.
然后问题就在于特征的成本是否因其好处而合理.
为了工作,必须考虑,设计,指定,实施,测试,记录并将其发送给客户.这是一个"产生错误"的功能,因此必须编写错误消息并将其翻译成几十种语言,文档也必须如此.实施该功能所花费的五分钟就可以转化为许多人付出相当多的工作时间.
但是,这实际上并不是相关成本.的机会成本是相关成本.预算是有限的,功能不是免费的,因此任何实现的功能都意味着必须削减一些其他功能; 您希望C#的哪个功能被剪切以获得此功能?在失去从中获益不能够做一个更好的特点是机会成本.
我还注意到你提出的功能对任何人来说都没有明显的好处,这对设计委员会来说是一个艰难的卖点.也许我没有看到令人信服的好处; 如果是的话,它是什么?
有什么场景可以有用吗?
没有人想到."拒绝不明显有用的程序"不是C#的设计目标.
Ale*_*kov 17
您可以将任何基础整数类型的值(我认为int默认情况下)转换为枚举 - 所以(MyConfusingEnum)42现在将是该枚举类型.
我认为一般来说这不是一个好主意,但可能存在"枚举"值来自外部源并且代码看起来更好的情况enum.
示例(假设代码在Enum中填充了一些"基于int的状态":
enum ExternalDeviceState {};
ExternalDeviceState GetState(){ ... return (ExternalDeviceState )intState;}
bool IsDeviceStillOk(ExternalDeviceState currentState) { .... }
Run Code Online (Sandbox Code Playgroud)
规范确实允许空枚举:
14.1枚举声明
枚举声明声明了一个新的枚举类型.枚举声明以关键字enum开头,并定义枚举的名称,可访问性,基础类型和成员.
enum-declaration:
attributesopt enum-modifiersopt enum identifier
enum-base(opt) enum-body ;(opt)
enum-base:
: integral-type
enum-body:
{ enum-member-declarations(opt) }
{ enum-member-declarations , }
Run Code Online (Sandbox Code Playgroud)
请注意,enum-member-declarations(opt)显式标记为变体,其中没有任何内容{}.
use*_*702 14
Activator.CreateInstance<MyConfusingEnum>();是一样的new MyConfusingEnum().(docs)
调用枚举的构造函数会为您0提供值.
由于设计决策,枚举可以具有对支持类型(通常int)有效的任何值,它不必是枚举中定义的值.
出于设计决策的原因,我可以在一个标题为"为什么将int int int to invalid enum value not throw exception?"的问题上指向这个答案.
@AlexeiLevenkov提供了允许空枚举的规范,我们可以猜测,这是因为任何支持类型值都有效,所以允许空枚举.
有什么场景可以有用吗?
正如其他人已经提到的那样,您可以通过简单的强制转换将此基础类型允许的任何值分配给此枚举.这样,在int会使事情混乱的情况下,您可以强制执行类型检查.例如:
public enum Argb : int {}
public void SetColor(Argb a) { ....
Run Code Online (Sandbox Code Playgroud)
或者你想要一些扩展方法,而不是使用它们来填充int数据类型
public static Color GetColor(this Argb value) {
return new Color( (int)value );
}
public static void Deconstruct( this Argb color, out byte alpha, out byte red, out byte green, out byte blue ) {
alpha = (byte)( (uint)color >> 24 );
red = (byte)( (uint)color >> 16 );
green = (byte)( (uint)color >> 8 );
blue = (byte)color;
}
Run Code Online (Sandbox Code Playgroud)
并用它作为
var (alpha, red, green, blue) = color;
Run Code Online (Sandbox Code Playgroud)