C# 使用LayoutKind.Explicit绕过使用“;“不安全”;指针?

C# 使用LayoutKind.Explicit绕过使用“;“不安全”;指针?,c#,unsafe-pointers,layoutkind.explicit,C#,Unsafe Pointers,Layoutkind.explicit,我有一些代码可以使用指针对数据块执行异或运算,这很快,但我想消除对程序集的“不安全”要求。如果我将其更改为使用LayoutKind.Explicit并在“byte[]”上覆盖一个“ulong[]”,我基本上做了与指针相同的事情,但这似乎同样危险。这两者之间的主要区别在于,“安全”版本的速度大约是“不安全”版本的1/2 这是绕过“不安全”程序集的合法方法,还是一次访问字节[]1字节是以安全方式执行此操作的唯一合法方法 private unsafe static void UnsafeEncode(

我有一些代码可以使用指针对数据块执行异或运算,这很快,但我想消除对程序集的“不安全”要求。如果我将其更改为使用LayoutKind.Explicit并在“byte[]”上覆盖一个“ulong[]”,我基本上做了与指针相同的事情,但这似乎同样危险。这两者之间的主要区别在于,“安全”版本的速度大约是“不安全”版本的1/2

这是绕过“不安全”程序集的合法方法,还是一次访问字节[]1字节是以安全方式执行此操作的唯一合法方法

private unsafe static void UnsafeEncode(
    byte[] buffer, int bufPos, ulong[] vector, int SectionLength, byte vectorIndex)
{
    fixed (byte* p = &buffer[bufPos])
    {
        ulong* pCur = (ulong*)p;
        ulong* pEnd = pCur + SectionLength;
        while (pCur < pEnd)
        {
            *pCur ^= vector[vectorIndex++];
            pCur++;
        }
    }
}

[StructLayout(LayoutKind.Explicit)]
private struct ArrayOverlay
{
    [FieldOffset(0)]
    public byte[] Bytes;
    [FieldOffset(0)]
    public ulong[] Longs;
}

private static void SafeEncode(
    byte[] buffer, int bufPos, ulong[] vector, int SectionLength, byte vectorIndex)
{
    var overlay = new ArrayOverlay { Bytes = buffer };
    int shiftleft = (bufPos & 7) << 3;
    int pos = bufPos >> 3;
    if (shiftleft == 0)
    {
        for (int i = 0; i < SectionLength; i++)
            overlay.Longs[i + pos] ^= vector[vectorIndex++];
    }
    else
    {
        int shiftright = (64 - shiftleft) & 63;
        ulong oldVec = 0;
        for (int i = 0; i < SectionLength; i++)
        {
            var vec = vector[vectorIndex++];
            overlay.Longs[i + pos] ^= (vec << shiftleft) | (oldVec >> shiftright);
            oldVec = vec;
        }
        overlay.Longs[SectionLength + pos] ^= (oldVec >> shiftright);
    }
}
private不安全静态void UnsafeEncode(
字节[]缓冲区,int-bufPos,ulong[]向量,int-SectionLength,字节向量索引)
{
已修复(字节*p=&缓冲区[bufPos])
{
ulong*pCur=(ulong*)p;
ulong*pEnd=pCur+截面长度;
同时(pCur3;
if(shiftleft==0)
{
对于(int i=0;ishiftright);
oldVec=vec;
}
overlay.Longs[SectionLength+pos]^=(oldVec>>shiftright);
}
}
这是绕过“不安全”程序集的合法方法,还是一次访问字节[]1字节是以安全方式执行此操作的唯一合法方法

private unsafe static void UnsafeEncode(
    byte[] buffer, int bufPos, ulong[] vector, int SectionLength, byte vectorIndex)
{
    fixed (byte* p = &buffer[bufPos])
    {
        ulong* pCur = (ulong*)p;
        ulong* pEnd = pCur + SectionLength;
        while (pCur < pEnd)
        {
            *pCur ^= vector[vectorIndex++];
            pCur++;
        }
    }
}

[StructLayout(LayoutKind.Explicit)]
private struct ArrayOverlay
{
    [FieldOffset(0)]
    public byte[] Bytes;
    [FieldOffset(0)]
    public ulong[] Longs;
}

private static void SafeEncode(
    byte[] buffer, int bufPos, ulong[] vector, int SectionLength, byte vectorIndex)
{
    var overlay = new ArrayOverlay { Bytes = buffer };
    int shiftleft = (bufPos & 7) << 3;
    int pos = bufPos >> 3;
    if (shiftleft == 0)
    {
        for (int i = 0; i < SectionLength; i++)
            overlay.Longs[i + pos] ^= vector[vectorIndex++];
    }
    else
    {
        int shiftright = (64 - shiftleft) & 63;
        ulong oldVec = 0;
        for (int i = 0; i < SectionLength; i++)
        {
            var vec = vector[vectorIndex++];
            overlay.Longs[i + pos] ^= (vec << shiftleft) | (oldVec >> shiftright);
            oldVec = vec;
        }
        overlay.Longs[SectionLength + pos] ^= (oldVec >> shiftright);
    }
}
这是合理的,因为它1)有效,2)可以产生正确的结果

当然,这样做并不一定“安全”,因为你可以做一些“令人讨厌”的事情,但它仍然会起作用。在这种情况下,您肯定违反了安全代码的精神,因为您可以做“安全”代码中不允许的事情,例如有效地绕过数组长度检查并导致缓冲区溢出

一次访问一个元素更符合“安全”代码的精神,但有时使用这样的技巧很有价值,因为它在需要时提供了一种性能机制。如果特定场景需要性能,而正常机制无法充分执行,这可能是一种使代码“工作”的方法,因为它符合您的规范(性能要求),而不会违反将程序集标记为不安全的安全约束