《CLR via C#》基本类型.枚举类型和位标志

15.枚举类型和位标志

15.1枚举类型

枚举类型Enum直接从System.Enum派生,后者从System.ValueType派生,而后者从System.Object派生,所以,枚举类型是值类型,但和其他值类型不一样,枚举类型不能定义任何方法(不过可以通过扩展方法模拟添加方法,15.3节会讲)、属性或事件。
枚举类型要和另一个类型结合使用,经常作为需要它的类型里的方法参数、返回类型、属性和字段使用。
枚举类型建议与需要它的类型同级,而不是嵌套定义在需要它的类型中。
枚举类型举例:

internal enum Color // 枚举类型的基本类型默认为System.Int32
{
    // 以下的都为常量(const)字段,都叫做符号
    White, // 编译器将White看成这种代码:public const Color White = (Color) 0;,编译时用数值替换符号
    Red,
    Green,
    Blue,
    Orange
}

Enum类型提供了实例方法ToString()等,还提供了静态方法GetValues()(等价于Type类型提供的GetEnumValues())、GetNames()(等价于Type类型提供的GetEnumNames())等,举例:

static void Main(string[] args)
{
	Color c = Color.Blue; // 初始化枚举类型的对象
	Console.WriteLine(c.ToString()); // 输出Blue

	// 通过Enum提供的静态方法GetValues,来获得符号的名字
	Color[] colors = (Color[])Enum.GetValues(typeof(Color)); // GetValues返回一个Array
	foreach (var color in colors)
	    Console.WriteLine(color);
	// 通过泛型方法来优化上述代码
	colors = GetValues<Color>(); // 下方定义了该泛型方法
	foreach (var color in colors)
	    Console.WriteLine(color);
	// 通过Type提供的实例方法GetEnumValues,来获得符号的名字
	colors = (Color[])c.GetType().GetEnumValues();
	foreach (var color in colors)
	    Console.WriteLine(color);
	
	// 也可以通过Enum提供的静态方法GetNames或Type提供的实例方法GetNames,来获得符号的名字
	string[] names = Enum.GetNames(typeof(Color)); // names = c.GetType().GetEnumNames();
	foreach (var name in names)
	    Console.WriteLine(name);
}
public static TEnum[] GetValues<TEnum>() where TEnum : struct
{
    return (TEnum[])Enum.GetValues(typeof(TEnum));
}
15.2位标志

定义含有位标志的枚举类型时,应显示地为每个符号分配一个数值,每个符号都有单独的一个位处于on状态(也就是二进制表示中有一位为1),经常要定义一个值为0的None符号,还经常定义一些符号来代表常见的位组合(比如下方的ReadWrite)。

[Flags]
internal enum Actions
{
    None = 0,
    Read = 0x0001, // 用十六进制表示,每个独立的符号都是2的整数次方
    Write = 0x0002,
    ReadWrite, // ReadWrite是符号的组合,等价于“Read|Write”,可理解为“0x0001 | 0x0002 = 0x0003”
    Delete = 0x0004,
    Query = 0x0008,
    Sync = 0x0010
}

// 在Main函数里:
Actions actions = Actions.Write | Actions.Delete; // 0x0006,没有对应的符号,但由于Actions上存在[Flags]特性
Console.WriteLine(actions.ToString()); // 所以,ToString方法把0x0006视为一组位标志,输出为:Write, Delete
// 如果Actions上没有[Flags]特性,输出就为6

上面讲的是如何将数值转换为标志字符串(以逗号分隔的符号字符串),下面讲的是如何将标志字符串转换为数值,用Enum提供的静态方法Parse和TryParse:

Console.WriteLine((int)Enum.Parse(typeof(Actions), "Delete", true)); // 第三个参数表示:是否辨别大小写, 输出4
Actions a = (Actions)Enum.Parse(typeof(Actions), "Write", true);
Console.WriteLine(a); // 输出:Write
15.3向枚举类型添加方法

利用C#的扩展方法模拟向枚举类型添加方法:

internal static class ActionsExtensionMethods
{
    public static Actions Set(this Actions flags, Actions setFlags) // 向flags字符里添加setFlags字符
    {
        return flags | setFlags;
    }
}

// 在Main函数里:
Actions ac = Actions.Sync;
ac = ac.Set(Actions.Read);
Console.WriteLine(ac.ToString()); // 输出:Read, Sync
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值