当我在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中,但是没有办法使用它(除非你开始搞乱反思)?是不是因为一些开发人员没有达到截止日期并且完成了一半的工作?即使如此,为什么代码不可用,但该领域是? 我希望有充分的理由。
我想说清楚。我不需要有关如何处理大端值的解决方案。我确实有一个解决方案。解决方案实际上已在我的问题中显示。
答案 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)
如果您想要一个允许您设置字节序的实现,请参阅http://snipplr.com/view/15179/adapt-systembitconverter-to-handle-big-endian-network-byte-ordering-in-order-to-create-number-types-from-bytes-and-viceversa/。
答案 6 :(得分:0)
我很确定他们将其设置为true
而false
不可能因为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);
}