我正在尝试获得使用 C#.NET 处理位的基本技能。我昨天发布了一个示例,其中包含一个需要位操作的简单问题,这使我发现有两种主要方法 - 使用
bitwise operators
或使用 .NET 抽象,例如 BitArray
(如果有更多构建,请告诉我-用于处理 .NET 中除 BitArray
以外的位的工具以及如何查找更多信息(如果有)?)。
我知道
bitwise operators
工作得更快,但使用 BitArray
对我来说更容易,但我真正努力避免的一件事是学习不好的做法。尽管我个人更喜欢 .NET 抽象,但我想知道在实际程序中我实际上更适合学习和使用哪个。考虑到这一点,我很想认为 .NET 抽象并没有那么糟糕,毕竟必须有理由存在,也许作为初学者,学习抽象并随后通过低级操作提高我的技能会更自然,但这只是随意的想法。
这实际上取决于你用它做什么。当速度更受关注时,我会说使用按位运算,因为它们的开销要少得多。否则,BitArray 应该没问题。相关的主要开销是函数调用以及对您可以执行的“技巧”的一些限制。
例如,如果您想要在值中设置位 0、3 或 4 时执行某些操作:
if((value & 0b11001)>0) //not sure this is valid syntax, but you get the idea
{
//do stuff
}
由于整数是本机 CLR 类型,因此几乎直接转换为 3 个本机操作码:
mov
、and
和 cmp
对于 BitArray,我认为最有效的方法是:
if(value[0] || value[3] || value[4])
{
//...
}
其中(假设不是 JIT),这相当于最多 3 个轻复杂度的函数调用。从 BitArray 的支持整数(我假设)获取位值的最简单方法如下所示:
bool GetBit(int which)
{
return value & (1 << which)>0;
}
这基本上意味着它相当于慢了大约 2 倍仅一位对于这个超级简单的情况,这意味着慢了大约 6 倍,因为我们正在检查 3 位。
对于 BitArray 来说,副本可能更昂贵,因为它们不是本机 CLR 类型。我怀疑大部分开销都被 JIT 消除了,但仍然需要考虑,特别是在针对紧凑框架时。
基本上,只有当您不需要对 BitArray 进行复杂的按位运算时才使用它们。
注意:您还可以使用在整数和 BitArray 之间进行转换的混合方法,但这也会产生相当大的开销。
我想知道在实际程序中我实际上更好地学习和使用哪个。
学习它们。它们并不难理解,您可以想象其中一个比另一个更好的场景。
虽然我同意上面的@Marc Gravell,但如果我需要处理大量的位(并且速度不是太大的问题),我只会考虑使用 BitArray,但如果你最终在这种情况下,无论如何你都可能做错了什么。
编程时请始终牢记这一点:
“没有什么问题是通过添加另一层间接层无法解决的,除了有太多间接层的问题”。 - 大卫惠勒(第)
通过使用 BitArray,您可以添加一个间接层,该层抽象了如何管理位以及生成和操作每个位的值的详细信息。这通常是一件好事,值得鼓励;它创建了更干净、更优雅、更易于阅读的代码。
但是,当您需要做一些复杂的事情时会发生什么,而 BitArray 不允许您做(或者很难做)?到那时,你的设计就“过于抽象”了;抽象级别阻止您做您想做的事情,因为它们“简化”了太多。这是一个用更少的抽象进行重构的信号,在这种情况下使用按位运算符需要更多的关注和理解,但基本上会对一组位执行任何可能的操作。
简而言之,使用 BitArray 来解决你的问题,直到使用 BitArray 成为它自己的问题为止。不用担心没有 BitArray 你要做什么;可以担心“是否以及何时”有必要。只是不要忘记如何使用按位运算符,或者它们的存在。
[...] 在我能想到的几乎所有常见场景中,操作员方法都是首选。我唯一一次查看 BitArray 是当我需要一组
任意大的标志时,其中 a: 非常罕见,而 b: 通过简单的字节数组或 int 数组来实现是微不足道的无论如何 – 马克·格拉维尔 2012 年 9 月 13 日 15:41