zoukankan      html  css  js  c++  java
  • “多态枚举”数值如何判断?

    枚举的作用就是用“字面量”的形式(附带智能提示)取代纯粹的数字化。假设某一个程序中有4盏灯,同时该程序带有一个输入源信号来输入究竟是那个灯点亮——显然定义一个枚举远远胜过用数字(1,2,3,4)表示具体某个灯亮好得多。因此枚举和数值往往是密不可分的。通常情况下枚举第一项默认是0,以后每项递增1;但是某些情况下(例如“多态枚举”——指一个枚举值可能包含多种枚举状态)的情况下,你完全为某些枚举指定对应的值,而且必须如此(理由后面说明)。譬如判断任意一个文件在Windows下的状态(假设3种):

    [C#]

    public enum FileAttributes
    {
       Normal = 1
       Hidden = 1<<1
       ReadOnly = 1<<2
    }

    [VB.NET]

    Public Enum FileAttributes
        Normal = 1
        Hidden = 1<<1
        [ReadOnly] = 1 << 2
    End Enum

    之所以要为每个枚举单独指定对应的数值,其原因在于一个文件不可能单独是“一种状态”(比如一个文本文件可能具备“隐藏”和“只读”双态),显然单独用一个枚举值根本无法表示,而且要把每种状态的组合列出也根本不可能;不过大家应该清楚一点——那就是枚举和数值之间的转换关系:

    1)当把一个数字转换成枚举,且这个数字映射到某个特定的枚举值,则直接输出该枚举值。

    2)当把一个数字转换成枚举,且这个数字无法映射到某个特定的枚举值,则直接输出该数字。

    因此.net中允许枚举进行“与或非”的操作——其中“或”操作等同于“+”(这个枚举不支持),把不同的枚举映射的数值求和,那么所得到的结果自然也就是包含多个枚举值的结果。

    这样求和有什么先决条件么?显然是有的。因为“或”运算是“全1得0,见1得1”(“全1”表示两个比特位都是1,那么得到0,例如二进制:1+1=0)。这样的话,如果枚举值是按照默认的“递增”的话,显然会造成数据上的混乱(譬如一开始0,第二项1,那么“或”变成1,以后你再也推断不出那个“0”对应的枚举值曾经用过;再譬如从2开始,第二项3,那么“或”的结果是5,“5”的二进制为“0000 0101",这样的话“2”和“3”其实也就无法得到了(因为“或”的缘故乱套了)。

    要使的其“不乱套”,唯一的方法就是每个枚举值取“2”的N次方(理由很简单:因为2的N次方只有特定位为1,其余均为0,这样“或”不会导致“1变成0”的惨剧)。例如示例代码中每个枚举值都是前一次“左移一位”(本质是2的N次方!),这样“或”的结果是0000 0001+0000 0010=0000 0011(十进制3)。

    对于我们而言,要判断某个“多态枚举”是否包含特有值,只需把这个值与“特定值”进行“与”操作(因为“与”是“见0得0,全1得1”,可以屏蔽其它位而保留特定位)。之前说过“2的N次方”只有特定位是1,那么“或”之后对其“与”,则只需判断特定位是否为1即可了。代码如下(假设FileAttributes是一个已经定义并且赋值的枚举变量)。

    [C#]

    if(FileAttributes & FileAttributes.Hidden == File.Attributes.Hidden)
    {
       ………………
    }

    [VB.NET]

    If (FileAttributes And FileAttributes.Hidden = FileAttributes.Hidden) Then
      ………………
    
    End If


     同样地,Enum中有一个Parse(或者TryParse)方法允许我们把枚举名称(或者枚举名称对应的数值)转化成相应的枚举类型。这里如果输出多个枚举,自动做“或”运算:

    下面可以做一个实验:

    [C#]

    enum Colors { None = 0, Red = 1, Green = 2, Blue = 3 };
    string
    [] colorStrings = { "Red,Green" }; foreach (string colorString in colorStrings) { Colors colorValue; if (Enum.TryParse(colorString, out colorValue)) Console.WriteLine(colorValue); }

    [VB.NET]

    Enum Colors
    None = 0
    Red = 1
    Green = 2
    Blue = 3
    End Enum
    Dim
    colorStrings As String() = {"Red,Green"} For Each colorString As String In colorStrings Dim colorValue As Colors If [Enum].TryParse(colorString, colorValue) Then Console.WriteLine(colorValue) End If Next

    如果直接输出“colorValue”,那么结果是“3”,恰恰是Red+Green的枚举值。(是“或”关系)。

    记住:“枚举”和“数值”是一一对应的,否则就会出现“张冠李戴”的错误,啼笑皆非:

    [C#]

    public class Example
    {
         enum Colors { None = 0, Red = 1, Green = 2, Blue = 3 };
    
       public static void Main()
       {
          string[] colorStrings = {  "Red,Green" };
          foreach (string colorString in colorStrings)
          {
             Colors colorValue;
             if (Enum.TryParse(colorString, out colorValue))        
                Console.WriteLine(colorValue);
          }
       }
    }

    [VB.NET]

    Public Class Example
        Private Enum Colors
            None = 0
            Red = 1
            Green = 2
            Blue = 3
        End Enum
    
        Public Shared Sub Main()
            Dim colorStrings As String() = {"Red,Green"}
            For Each colorString As String In colorStrings
                Dim colorValue As Colors
                If [Enum].TryParse(colorString, colorValue) Then
                    Console.WriteLine(colorValue)
                End If
            Next
        End Sub
    End Class

    "Red"+"Green"=3,因此最终输出的是Blue,因为Blue=3。

  • 相关阅读:
    mac 外接显示屏的坑
    ssh 多秘钥管理和坑
    CircleCI 前端自动部署
    jest 事件测试
    await Vue.nextTick() 的含义分析
    Jest 里面需要注意的几个小细节
    element 库 date-picker 的 disabledDate 的坑
    jest 提示 Unexpected identifier 的解决方案
    preventDefault 和 stopPropagation
    数据库:Flask-SQLAlchemy
  • 原文地址:https://www.cnblogs.com/ServiceboyNew/p/2595229.html
Copyright © 2011-2022 走看看