在C#中有一些我无法理解的东西.您可以将超出范围int转换为a enum,编译器不会退缩.想象一下enum:
enum Colour
{
Red = 1,
Green = 2,
Blue = 3
}
Run Code Online (Sandbox Code Playgroud)
现在,如果你写:
Colour eco;
eco = (Colour)17;
Run Code Online (Sandbox Code Playgroud)
编译器认为没问题.还有运行时.呃?
为什么C#团队决定实现这一目标?我认为,在这样的场景中,这个决定忽略了使用枚举的重点:
void DoSomethingWithColour(Colour eco)
{
//do something to eco.
}
Run Code Online (Sandbox Code Playgroud)
在像C#这样的强类型语言中,我想假设它eco总是具有合法Colour价值.但这种情况并非如此.程序员可以调用我的方法,其值为17 eco(如前面的代码片段所示),因此我的方法中的代码不能假定它eco具有合法Colour值.我需要明确地测试它并按照我的要求处理特殊值.为什么是这样?
在我的拙见中,如果编译器在将超出范围int转换为a时发出错误(甚至是警告)消息enum,如果int在编译时已知该值,则会更好.如果没有,运行时应该在赋值语句中抛出异常.
你怎么看?这有什么原因吗?
(注意:这是我在很久以前在我的博客上发布的一个问题,但没有得到任何信息回复.)
Hen*_*man 31
猜猜"为什么"总是危险的,但请考虑一下:
enum Direction { North =1, East = 2, South = 4, West = 8 }
Direction ne = Direction.North | Direction.East;
int value = (int) ne; // value == 3
string text = ne.ToString(); // text == "3"
Run Code Online (Sandbox Code Playgroud)
当[Flags]属性放在枚举前面时,最后一行会变为
string text = ne.ToString(); // text == "North, East"
Run Code Online (Sandbox Code Playgroud)
joh*_*y g 15
不知道为什么,但我最近发现这个"功能"非常有用.前几天我写了这样的东西
// a simple enum
public enum TransmissionStatus
{
Success = 0,
Failure = 1,
Error = 2,
}
// a consumer of enum
public class MyClass
{
public void ProcessTransmissionStatus (TransmissionStatus status)
{
...
// an exhaustive switch statement, but only if
// enum remains the same
switch (status)
{
case TransmissionStatus.Success: ... break;
case TransmissionStatus.Failure: ... break;
case TransmissionStatus.Error: ... break;
// should never be called, unless enum is
// extended - which is entirely possible!
// remember, code defensively! future proof!
default:
throw new NotSupportedException ();
break;
}
...
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,我该如何测试最后一个案例条款?假设有人可能延长TransmissionStatus而不更新其消费者是完全合理的,就像MyClass上面的穷人一样.但是,我还是想在这种情况下验证它的行为.一种方法是使用铸造,例如
[Test]
[ExpectedException (typeof (NotSupportedException))]
public void Test_ProcessTransmissionStatus_ExtendedEnum ()
{
MyClass myClass = new MyClass ();
myClass.ProcessTransmissionStatus ((TransmissionStatus)(10));
}
Run Code Online (Sandbox Code Playgroud)
我当然看到了Cesar的观点,我记得这也让我很困惑.在我看来,枚举,在他们目前的实施中,确实有点太低水平和漏洞.在我看来,这个问题会有两种解决方案.
1)如果其定义具有FlagsAttribute,则只允许将任意值存储在枚举中.这样,我们可以在适当时(并显式声明)继续将它们用于位掩码,但是当简单地用作常量的占位符时,我们将在运行时检查值.
2)引入一个名为say,bitmask的独立原始类型,它允许任何ulong值.同样,我们仅将标准枚举限制为声明值.这样可以让编译器为您分配位值.所以这:
[Flags]
enum MyBitmask
{
FirstValue = 1, SecondValue = 2, ThirdValue = 4, FourthValue = 8
}
Run Code Online (Sandbox Code Playgroud)
等同于:
bitmask MyBitmask
{
FirstValue, SecondValue, ThirdValue, FourthValue
}
Run Code Online (Sandbox Code Playgroud)
毕竟,任何位掩码的值都是完全可预测的,对吧?作为一名程序员,我非常乐意将这些细节抽象出去.
现在还为时已晚,我想我们永远都会坚持当前的实施.:/