考虑以下代码:
namespace ConsoleApplication1 {
class Program {
public static void Main (string[] args) {
var en = (TestEnum)Enum.Parse(typeof(TestEnum), "AA");
Console.WriteLine(en.ToString());
Console.ReadKey();
}
}
public enum TestEnum {
AA = 0x01,
AB = 0x02,
AC = 0x03,
BA = 0x01,
BB = 0x02,
BC = 0x03
}
}
Run Code Online (Sandbox Code Playgroud)
如果执行此操作,变量en将获得值TestEnum.BA.现在我从中学到了枚举标志应该是唯一的,或者你得到这些意想不到的东西,但我确实不明白这里发生了什么.
更奇怪的部分是,当我将[Flags]属性添加到TestEnum时,它解决了问题并返回TestEnum.AA而不是TestEnum.BA,但对于原始枚举(更大,约200个成员)我发现这个问题这没有什么区别.
我的理解是枚举是一种值类型,所以当你定义自己的标志时,它会将内存中的值存储为0x01(对于TestEnum.AA),当你将它从对象转换为TestEnum时,它将执行查找那个标志值并找到TestEnum.BA.
运行以下行也可以确认这一点:
var en = (TestEnum)(object)TestEnum.AA;
Console.WriteLine(en.ToString());
Run Code Online (Sandbox Code Playgroud)
哪个会输出: BA
所以我的问题是:这到底发生了什么?更重要的是,为什么添加Flags属性会有所不同?
Mat*_*son 12
首先,这与此无关Enum.Parse().默认情况下int,枚举的基础类型是,因此在您的示例中TestEnum.AA,TestEnum.BA它们都存储为,1并且无法区分它们.
见以下代码:
Console.WriteLine(TestEnum.AA); // Prints BA
Console.WriteLine(TestEnum.BA); // Prints BA
Run Code Online (Sandbox Code Playgroud)
其次,设置[Flags]属性改变输出的原因是因为在确定字符串时采用了不同的代码路径.
private static String InternalFormat(RuntimeType eT, Object value)
{
if (!eT.IsDefined(typeof(System.FlagsAttribute), false)) // Not marked with Flags attribute
{
// Try to see if its one of the enum values, then we return a String back else the value
String retval = GetName(eT, value);
if (retval == null)
return value.ToString();
else
return retval;
}
else // These are flags OR'ed together (We treat everything as unsigned types)
{
return InternalFlagsFormat(eT, value);
}
}
Run Code Online (Sandbox Code Playgroud)
注意GetName()如果[Flags]未设置则调用如何调用,否则InternalFlagsFormat()调用.
最终执行GetName()二进制搜索以找到值,而InternalFlagsFormat()最终执行线性搜索以查找值.
InternalFlagsFormat()必须进行线性搜索,因为它可能需要设置多个值(例如"X | Y | Z"),因此Microsoft为它实现了O(N)解决方案.然而,GetName()他们寻求更高效的O(Log2(N))解决方案.
二元搜索可以(并且确实)找到与线性搜索不同的重复值,因此存在差异.
| 归档时间: |
|
| 查看次数: |
210 次 |
| 最近记录: |