当我在.NET BinaryReader类中遇到此代码时,我只是想优化一些代码:
[CLSCompliant(false)]
[__DynamicallyInvokable]
public virtual ulong ReadUInt64()
{
this.FillBuffer(8);
return (ulong) (uint) ((int) this.m_buffer[4] | (int) this.m_buffer[5] << 8 | (int) this.m_buffer[6] << 16 | (int) this.m_buffer[7] << 24) << 32 | (ulong) (uint) ((int) this.m_buffer[0] | (int) this.m_buffer[1] << 8 | (int) this.m_buffer[2] << 16 | (int) this.m_buffer[3] << 24);
}
我想知道为什么ulong在两个部分中移动然后组合而不是仅仅在0,8,16,...,56中移位。
我还想解释一下这里使用的多种铸件。
编辑:当我在安装了ReSharper的VS2013中输入时,显示如下:
正如你所看到的,第二个ulong变暗了,这意味着它甚至没有使用过。看来缺少一对括号。这是对的吗?
答案 0 :(得分:3)
首先,让我们以一种更易读的形式重写它:
CREATE PROCEDURE [dbo].[UPDATE_TRAINEE_EVENTS]
@EVENTID int,
@EVENTTYPEID int,
@EVENTDATE datetime,
@STAFFID int,
@REVIEWNO int,
@COMMENTS varchar(2100),
@DESTINYVERIFIED int,
@DESTINYVERIFIEDBY int,
@DESTINYVERIFIEDDATE datetime,
@REASONFORSUSPENSIONID int,
@RETURNTOWORKDATE datetime,
@ContactDetailsUpdated int,
@RETENTION_STATUS_ID int,
@RETENTION_REASON_ID int,
@NonReview int,
@FalsifiedEventReason int,
@SusReqReasonID int,
@SusReqReturnDate datetime
AS
......
现在很清楚这是做什么的。
它将低32位和高32位组合成两个单独的(ulong)(uint)(
(int) this.m_buffer[4] |
(int) this.m_buffer[5] << 8 |
(int) this.m_buffer[6] << 16 |
(int) this.m_buffer[7] << 24)
<< 32 |
(ulong)(uint)(
(int) this.m_buffer[0] |
(int) this.m_buffer[1] << 8 |
(int) this.m_buffer[2] << 16 |
(int) this.m_buffer[3] << 24)
值(通过在将它们转换为uint
之后移动字节),然后将两个结果int
值转换为int
,将高32位移位32,最后将它们“或”运算得到结果。
这样做的原因是因为移位32位值比移位64位值更快。如果代码将所有字节转换为ulong
然后移位它们,则会更慢。
另请注意,组合字节的顺序是“little endian”格式。
唯一显而易见的事情是第一次演员ulong
,可能就是(ulong)(uint)
。如果删除所有不必要的强制转换,它看起来像这样:
(ulong)
现在你可能想知道为什么你不能仅仅转变为(ulong)(
buffer[4] |
buffer[5] << 8 |
buffer[6] << 16 |
buffer[7] << 24)
<< 32 |
(uint)(
buffer[0] |
buffer[1] << 8 |
buffer[2] << 16 |
buffer[3] << 24);
而不是ulong
。
答案如下。假设代码是这样的:
uint
由于转换为(ulong)(
buffer[4] |
buffer[5] << 8 |
buffer[6] << 16 |
buffer[7] << 24)
<< 32 |
(ulong)( // This seems more natural...
buffer[0] |
buffer[1] << 8 |
buffer[2] << 16 |
buffer[3] << 24);
,表达式的第一部分使用ulong.operator<<()
移位。这会返回(ulong)
。
然而,表达式的第二部分没有移位,当它与第一个表达式进行OR运算时,它会提示编译器警告:
警告CS0675:在符号扩展操作数上使用按位或运算符;考虑先投射到较小的无符号类型
Eric Lippert有a blog about this warning你应该阅读。
无论如何,因为在第一部分中投射到(ulong)
而第二部分投射到(ulong)
时看起来很奇怪,我相当肯定他们会进行完全明确的演员以避免混淆读者。