在 C# 中使用位掩码
假设我有以下内容
int susan = 2; //0010
int bob = 4; //0100
int karen = 8; //1000
,我将 10 (8 + 2) 作为参数传递给方法,我想将其解码为苏珊和凯伦,
我知道 10 是 1010
,但是我如何做一些逻辑来查看特定的位被检查,
if (condition_for_karen) // How to quickly check whether effective karen bit is 1
现在我能想到的就是检查我传递的数字是否是
14 // 1110
12 // 1100
10 // 1010
8 // 1000
当我在现实世界场景中有大量实际位时,这似乎不切实际,使用掩码的更好方法是什么检查我是否满足just karen的条件?
我可以考虑向左移动然后返回,然后向右移动然后返回到除我感兴趣的之外的清除位,但这似乎也过于复杂。
Let's say I have the following
int susan = 2; //0010
int bob = 4; //0100
int karen = 8; //1000
and I pass 10 (8 + 2) as a parameter to a method and I want to decode this to mean susan and karen
I know that 10 is 1010
but how can I do some logic to see if a specific bit is checked as in
if (condition_for_karen) // How to quickly check whether effective karen bit is 1
Right now all i can think of is to check whether the number i passed is
14 // 1110
12 // 1100
10 // 1010
8 // 1000
When I have a larger number of actual bits in my real world scenario, this seems impractical, what is a better way using a mask to just check whether or not I meet the condition for just karen?
I can think of shifting left then back then shifting right then back to clear bits other than the one I'm interested in, but this also seems overly complex.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
简单方法:
要设置标志,请使用逻辑“或”运算符
|
:并检查是否包含标志,使用
HasFlag
:Easy Way:
To set the flags use logical "or" operator
|
:And to check if a flag is included use
HasFlag
:按位“与”将屏蔽除“代表”Karen 的位之外的所有内容。只要每个人都由一个位位置表示,您就可以使用简单的方法检查多个人:
The bitwise 'and' will mask out everything except the bit that "represents" Karen. As long as each person is represented by a single bit position, you could check multiple people with a simple:
我在这里提供了一个示例,演示了如何将掩码作为 int 存储在数据库列中,以及稍后如何恢复掩码:
I have included an example here which demonstrates how you might store the mask in a database column as an int, and how you would reinstate the mask later on:
要组合位掩码,您需要使用按位-或。在简单的情况下,您组合的每个值都恰好有 1 位(如您的示例),这相当于将它们相加。然而,如果您有重叠的位,或对它们进行处理可以优雅地处理这种情况。
要使用掩码解码位掩码和值,如下所示:
To combine bitmasks you want to use bitwise-or. In the trivial case where every value you combine has exactly 1 bit on (like your example), it's equivalent to adding them. If you have overlapping bits however, or'ing them handles the case gracefully.
To decode the bitmasks you and your value with a mask, like so:
使用位掩码与单个布尔值的另一个真正好的理由是,作为一名 Web 开发人员,将一个网站集成到另一个网站时,我们经常需要在查询字符串中发送参数或标志。只要所有标志都是二进制的,使用单个值作为位掩码比发送多个值作为布尔值要简单得多。我知道还有其他方法可以发送数据(GET、POST 等),但查询字符串上的简单参数大多数时候足以满足非敏感项目的需要。尝试在查询字符串上发送 128 个布尔值以与外部站点通信。这还提供了不突破浏览器中 url 查询字符串限制的附加功能
One other really good reason to use a bitmask vs individual bools is as a web developer, when integrating one website to another, we frequently need to send parameters or flags in the querystring. As long as all of your flags are binary, it makes it much simpler to use a single value as a bitmask than send multiple values as bools. I know there are otherways to send data (GET, POST, etc.), but a simple parameter on the querystring is most of the time sufficient for nonsensitive items. Try to send 128 bool values on a querystring to communicate with an external site. This also gives the added ability of not pushing the limit on url querystrings in browsers
传统的方法是在
enum
上使用Flags
属性:然后您将按如下方式检查特定名称:
逻辑按位组合可能很难记住,所以我使用
FlagsHelper
类让自己的生活更轻松*:这将允许我将上面的代码重写为:
注意我还可以通过执行以下操作将
Karen
添加到集合中我可以用类似的方式删除
Susan
:*正如 Porges 指出的,.NET 4.0 中已经存在与上面
IsSet
方法等效的方法:< a href="http://msdn.microsoft.com/en-us/library/system.enum.hasflag.aspx" rel="noreferrer">Enum.HasFlag
。不过,Set
和Unset
方法似乎没有等效项;所以我仍然认为这个类有一些优点。注意:使用枚举只是解决这个问题的传统方法。您完全可以将上述所有代码转换为使用整数,它也能正常工作。
The traditional way to do this is to use the
Flags
attribute on anenum
:Then you'd check for a particular name as follows:
Logical bitwise combinations can be tough to remember, so I make life easier on myself with a
FlagsHelper
class*:This would allow me to rewrite the above code as:
Note I could also add
Karen
to the set by doing this:And I could remove
Susan
in a similar way:*As Porges pointed out, an equivalent of the
IsSet
method above already exists in .NET 4.0:Enum.HasFlag
. TheSet
andUnset
methods don't appear to have equivalents, though; so I'd still say this class has some merit.Note: Using enums is just the conventional way of tackling this problem. You can totally translate all of the above code to use ints instead and it'll work just as well.