15.1 枚举类型
- 枚举定义的符号是常量值. C#编译器编译时,会用数值替换符号,不再引用定义了符号的枚举类型.可能会出现一些版本问题.
- Enum.IsDefined(Type enumType, object value)方法被经常用于参数校验:
public void SetColor(ConsoleColor c)
{
if (!Enum.IsDefined(typeof(ConsoleColor), c))
{
throw new ArgumentOutOfRangeException(nameof(c), c, "无效颜色值");
}
}
- IsDefined方法必须慎用. 首先, IsDefined总是区分大小写;其次,IsDefined相当慢,因为它在内部使用了反射.
15.2 位标志
[Flags]
public enum FileAttributes
{
ReadOnly = 1,
Hidden = 2,
System = 4,
Directory = 16,
......
}
static void Main(string[] args)
{
//判断文件是否隐藏
String file = Assembly.GetEntryAssembly().Location;
FileAttributes attributes = File.GetAttributes(file);
Console.WriteLine("Is {0} hidden? {1}", file, (attributes & FileAttributes.Hidden) != 0);
//使用 HasFlag 方法(不推荐)
Console.WriteLine("Is {0} hidden? {1}", file, attributes.HasFlag(FileAttributes.Hidden));
//设置只读和隐藏特性
File.SetAttributes(file, FileAttributes.ReadOnly | FileAttributes.Hidden);
}
- 避免使用 HasFlag,因为会装箱.
- 永远不要对位标志枚举类型使用 IsDefined 方法. 因为无论传入数字或字符串,都只能进行简单匹配,通常会返回False.
15.3 向枚举类型添加方法
// flags 中是否包含 flagToTest
public static bool IsSet(this FileAttributes flags, FileAttributes flagToTest)
{
if (flagToTest == 0)
throw new ArgumentOutOfRangeException(nameof(flagToTest), "Value must not be 0");
return (flags & flagToTest) == flagToTest;
}
// flags 中是否不包含 flagToTest
public static bool IsClear(this FileAttributes flags, FileAttributes flagToTest)
{
if (flagToTest == 0)
throw new ArgumentOutOfRangeException(nameof(flagToTest), "Value must not be 0");
return !IsSet(flags, flagToTest);
}
// flags 中是否包含 testFlags 中的任何一个位标志
public static bool AnyFlagsSet(this FileAttributes flags, FileAttributes testFlags)
{
return (flags & testFlags) != 0;
}
//将 setFlags 中包含的位标志,添加到 flags 中
public static FileAttributes Set(this FileAttributes flags, FileAttributes setFlags)
{
return flags | setFlags;
}
//从 flags 中清除 指定的位标志(clearFlags)
public static FileAttributes Clear(this FileAttributes flags, FileAttributes clearFlags)
{
return flags & ~clearFlags;
}
//遍历 flags 中包含的位标志
public static void ForEach(this FileAttributes flags, Action<FileAttributes> processFlag)
{
if (processFlag == null) throw new ArgumentNullException(nameof(processFlag));
for (UInt32 bit = 1; bit != 0; bit <<= 1)
{
UInt32 temp = ((UInt32)flags) & bit;
if (temp != 0) processFlag((FileAttributes)temp);
}
}
返回目录