zoukankan      html  css  js  c++  java
  • <NET CLR via c# 第4版>笔记 第15章 枚举类型和位标志

    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);
                }
            }
    

    返回目录

  • 相关阅读:
    键盘过滤驱动
    多线程和多进程的差别(小结)
    Android UI设计规则
    怎样使用SetTimer MFC 够具体
    Chord算法(原理)
    POJ 1384 Piggy-Bank 背包DP
    Bulk Insert命令具体
    hibernate官方新手教程 (转载)
    教你用笔记本破解无线路由器password
    转换流--OutputStreamWriter类与InputStreamReader类
  • 原文地址:https://www.cnblogs.com/harry-wang/p/7307944.html
Copyright © 2011-2022 走看看