为了账号安全,请及时绑定邮箱和手机立即绑定

在C#中使用位掩码

在C#中使用位掩码

C#
米脂 2019-11-26 10:01:18
假设我有以下内容int susan = 2; //0010int bob = 4; //0100int karen = 8; //1000我将10(8 + 2)作为参数传递给方法,我想对此进行解码以表示susan和karen我知道10是1010但是我该怎么做才能看是否检查了特定的位if (condition_for_karen) // How to quickly check whether effective karen bit is 1现在我所能想到的就是检查我通过的号码是否14 // 111012 // 110010 // 10108 //  1000当我在现实世界中有大量实际位时,这似乎是不切实际的,有什么更好的方法使用遮罩来检查我是否满足卡伦的条件?我可以想到先左移然后再右移然后再清除以清除除我感兴趣的位以外的其他位,但这似乎过于复杂。
查看完整描述

3 回答

?
达令说

TA贡献1821条经验 获得超6个赞

传统方法是在上使用Flags属性enum:


[Flags]

public enum Names

{

    None = 0,

    Susan = 1,

    Bob = 2,

    Karen = 4

}

然后,您将按照以下方式检查特定名称:


Names names = Names.Susan | Names.Bob;


// evaluates to true

bool susanIsIncluded = (names & Names.Susan) != Names.None;


// evaluates to false

bool karenIsIncluded = (names & Names.Karen) != Names.None;

逻辑按位组合可能很难记住,因此我可以通过一FlagsHelper堂课* 使自己的生活更轻松:


// The casts to object in the below code are an unfortunate necessity due to

// C#'s restriction against a where T : Enum constraint. (There are ways around

// this, but they're outside the scope of this simple illustration.)

public static class FlagsHelper

{

    public static bool IsSet<T>(T flags, T flag) where T : struct

    {

        int flagsValue = (int)(object)flags;

        int flagValue = (int)(object)flag;


        return (flagsValue & flagValue) != 0;

    }


    public static void Set<T>(ref T flags, T flag) where T : struct

    {

        int flagsValue = (int)(object)flags;

        int flagValue = (int)(object)flag;


        flags = (T)(object)(flagsValue | flagValue);

    }


    public static void Unset<T>(ref T flags, T flag) where T : struct

    {

        int flagsValue = (int)(object)flags;

        int flagValue = (int)(object)flag;


        flags = (T)(object)(flagsValue & (~flagValue));

    }

}

这将允许我将以上代码重写为:


Names names = Names.Susan | Names.Bob;


bool susanIsIncluded = FlagsHelper.IsSet(names, Names.Susan);


bool karenIsIncluded = FlagsHelper.IsSet(names, Names.Karen);

注意,我还可以Karen通过执行以下操作添加到集合中:


FlagsHelper.Set(ref names, Names.Karen);

我可以Susan用类似的方式删除:


FlagsHelper.Unset(ref names, Names.Susan);

*正如Porges所指出的,IsSet.NET 4.0中已经存在上述方法的等效项:Enum.HasFlag。不过,Set和Unset方法似乎没有等效项。所以我仍然会说这堂课有一些优点。


注意:使用枚举只是解决此问题的常规方法。您可以完全翻译上面的所有代码以改为使用int,它也将正常工作。


查看完整回答
反对 回复 2019-11-26
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

if ( ( param & karen ) == karen )

{

  // Do stuff

}

按位“与”将掩盖除“代表”凯伦的位以外的所有内容。只要每个人都用一个位表示,就可以用简单的方法检查多个人:


if ( ( param & karen ) == karen )

{

  // Do Karen's stuff

}

if ( ( param & bob ) == bob )

  // Do Bob's stuff

}


查看完整回答
反对 回复 2019-11-26
  • 3 回答
  • 0 关注
  • 778 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信