IsLittleEndian在BitConverter类中的用例是什么?

时间:2011-06-20 03:28:39

标签: c# .net vb.net endianness bitconverter

当我在IsLittleEndian中发现BitConverter字段时,我感到非常高兴。我当然认为它应该在那里,我应该能够指定我喜欢的任何endian。好吧,我的幸福并没有持续多久。花了一些时间才发现没有办法设置场地。 该字段为readonly,在静态构造函数中仅设置为true

static BitConverter()
{
    IsLittleEndian = true;
}

有趣的是,该字段实际上是在代码中使用的。例如,ToInt32方法实现如下所示:

if (IsLittleEndian)
{
     return (((numRef[0] | (numRef[1] << 8)) | (numRef[2] << 0x10)) | (numRef[3] << 0x18));
}
return ((((numRef[0] << 0x18) | (numRef[1] << 0x10)) | (numRef[2] << 8)) | numRef[3]);

似乎ToInt32完全有能力处理小端和大端。

我的问题是:为什么有一段非常有用的代码已经实现并且坐在FCL中,但是没有办法使用它(除非你开始搞乱反思)?是不是因为一些开发人员没有达到截止日期并且完成了一半的工作?即使如此,为什么代码不可用,但该领域是? 我希望有充分的理由。

我想说清楚。我不需要有关如何处理大端值的解决方案。我确实有一个解决方案。解决方案实际上已在我的问题中显示。

7 个答案:

答案 0 :(得分:5)

不幸的是,IsLittleEndian字段只是通知您。但Jon Skeets MiscUtil库有一个很好的EndianBitConverter,支持小端和大端。还有endian感知的BinaryWriter / -Reader类。

以下是链接:http://www.yoda.arachsys.com/csharp/miscutil/

编辑:抱歉,但我没有更好的解释。我认为这应该包含在框架中,我想代码目前在那里,因此很容易将Converter移植到另一个架构。

但是暴露这种功能比仅仅公开这个领域要复杂得多。转换器是静态的,因此更改标志有效地改变了全局状态,并且在多线程场景中这将是灾难性的。要走的路可能是提供两个可以在本地实例化和使用的BitConverter对象(这就是MiscUtil所做的)。这需要额外的类和/或接口,因此可能是一个截止日期问题,暂时放弃了。我们希望它能在一段时间后添加。

答案 1 :(得分:3)

首先让我们确定类BitConverter是专为本地处理器的位强转换而设计的。这就是IsLittleEndian是只读的原因。因此,如果本地处理器是little-endian,则它不支持转换为big-endian或从big-endian转换,反之亦然。

虽然我不知道省略对一般字节序的支持的原因,但对我来说最合理的理由是性能。在整个框架中广泛用于其预期目的的类(转换到本机处理器的字节序的转换)应该尽可能高效。通过限制类的一般性,通过限制必须处理的案例来改善其性能。通过仅支持little-endian,它可能可以更快地测量

好的,现在我们谈到了问题的关键。如果类的整体设计只打算支持一个,那么为什么作者会包含处理little-endian和big-endian的代码?

同样,我们只能推测。但答案可能在于两个观察结果:

  • 引用IsLittleEndian 的反汇编代码在性能方面是一个不重要的案例
  • 编写可移植代码,如果它不影响性能,则良好的软件工程

您从ToInt32方法复制的代码不重要的原因是因为它仅用于未对齐内存。 99%的代码路径是位的直接不安全的“memcpy”。

即使从未对齐​​的内存转换确实发生,处理它的代码比raw方法效率低一个数量级。所以一个额外的条件并没有真正损害性能。

最终结果是:

  • BitConverter课程尽可能高效用于其有限目的
  • BitConverter的源代码仍可移植到大端处理器架构

答案 2 :(得分:2)

答案在于查看BitConverter类的reference source

相关摘录是:

        // This field indicates the "endianess" of the architecture.
        // The value is set to true if the architecture is
        // little endian; false if it is big endian.
#if BIGENDIAN
        public static readonly bool IsLittleEndian /* = false */;
#else
        public static readonly bool IsLittleEndian = true;
#endif

该标志由预处理器指令硬连接,因为编译特定版本框架的体系结构的字节序不会改变。

答案 3 :(得分:1)

根据MSDN文档IsLittleEndian,通知您(您的程序或BitConverter类)架构是Little还是Big Endian是很明智的。我并不认为有其他用途。

答案 4 :(得分:0)

它是根据achitecture类型在内部设置的。

来自docs

“不同的计算机体系结构使用不同的字节顺序存储数据。”Big-endian“表示最重要的字节位于单词的左端。”Little-endian“表示最重要的字节位于右端。字“。

修改

这是c#团队做出的设计决定。该函数能够从两种类型转换,因为它可以在两种类型的系统上使用。作为开发人员,你可以自行转换它。

“...... BitConverter的所有方法都接受或以SYSTEM字节顺序返回字节数组......”

int i = BitConverter.ToInt32(byte[] inputdata);
(manipulate i)
return BitConverter.GetBytes(i);

“如果数据永远不会离开您的应用程序的范围,这实际上工作正常。”

有关详细信息,请参阅this article

答案 5 :(得分:0)

答案 6 :(得分:0)

我很确定他们将其设置为truefalse不可能因为all versions of Windows are little-endian

现在,他们在一个永远不会将if (IsLittleEndian)设置为除IsLittleEndian以外的任何内容的类中执行true的问题很可能是一个简单的情况。这样,如果确实需要为big-endian编译.NET BCL,那么围绕一个赋值的简单#if / #else就足够了,而不必编写新代码。

我敢打赌Mono为某些操作系统和架构设置了false

编辑:我是对的。 Mono does the following。从技术上讲,其他代码都不需要添加,只是由于版权问题,他们必须在Mono中以不同的方式编写所有内容。

public static readonly bool IsLittleEndian = AmILittleEndian ();

static unsafe bool AmILittleEndian ()
{
  // binary representations of 1.0:
  // big endian: 3f f0 00 00 00 00 00 00
  // little endian: 00 00 00 00 00 00 f0 3f
  // arm fpa little endian: 00 00 f0 3f 00 00 00 00
  double d = 1.0;
  byte *b = (byte*)&d;
  return (b [0] == 0);
}