将sbyte []转换为bool []并将char []转换为short []

Nic*_*ick 12 c# casting

无论如何都要明确地施放/胁迫

  • sbyte[]byte[]bool[]
  • char[]short[]/ushort[]

在CIL你经常会看到诸如此类的东西

stelem Type sbyte (ldloc pArray) ldc_i4 1 ldc_i4 0 
Run Code Online (Sandbox Code Playgroud)

pArray[1] = true哪里做的pArray是一维类型的数组bool[].我想在c#中复制这个

(sbyte[])pArray[1] = 1;
Run Code Online (Sandbox Code Playgroud)

不幸的是,C#编译器不允许这样做.

xan*_*tos 17

无证技巧,玩法风险自负:

(例如在这里和许多其他地方显示)

[StructLayout(LayoutKind.Explicit)]
public struct ConvSByteBool
{
    [FieldOffset(0)]
    public sbyte[] In;
    [FieldOffset(0)]
    public bool[] Out;
}
Run Code Online (Sandbox Code Playgroud)

然后:

var bytes = new sbyte[] { -2, -1, 0, 1, 2 };
var conv = new ConvSByteBool { In = bytes }.Out;
bool b1 = conv[0]; // true
bool b2 = conv[1]; // true
bool b3 = conv[2]; // false
bool b4 = conv[3]; // true
bool b5 = conv[4]; // true
Run Code Online (Sandbox Code Playgroud)

请注意,这个技巧与泛型有点不兼容.不Conv<T, U>!

当源和目标中的元素大小相同(sizeof(sbyte) == sizeof(bool))时,该技巧最有效.否则有一些限制(在上面的链接问题中描述).


Mat*_*son 9

您可以使用new Span<T>MemoryMarshaltypes来执行此操作.

请注意,这仅适用于最新版本的C#,您现在必须使用NuGet包来提供库,但这会发生变化.

因此,例如,将char数组"转换"为短数组,您可以编写如下代码:

var         charArray  = new char[100];
Span<short> shortArray = MemoryMarshal.Cast<char, short>(charArray);

charArray[0] = 'X';
Console.WriteLine(charArray[0]); // Prints 'X'
++shortArray[0];
Console.WriteLine(charArray[0]); // Prints 'Y'
Run Code Online (Sandbox Code Playgroud)

这种方法是有记录的,不会制作任何数据的任何副本 - 而且它也非常高效(按设计).

请注意,这也适用于结构:

struct Test
{
    public int X;
    public int Y;

    public override string ToString()
    {
        return $"X={X}, Y={Y}";
    }
}

...

var testArray = new Test[100];
Span<long> longArray = MemoryMarshal.Cast<Test, long>(testArray);

testArray[0].X = 1;
testArray[0].Y = 2;

Console.WriteLine(testArray[0]); // Prints X=1, Y=2

longArray[0] = 0x0000000300000004;

Console.WriteLine(testArray[0]); // Prints X=4, Y=3
Run Code Online (Sandbox Code Playgroud)

还要注意,这可以让你做一些可疑的事情,比如:

struct Test1
{
    public int X;
    public int Y;

    public override string ToString()
    {
        return $"X={X}, Y={Y}";
    }
}

struct Test2
{
    public int X;
    public int Y;
    public int Z;

    public override string ToString()
    {
        return $"X={X}, Y={Y}, Z={Z}";
    }
}

...

var         test1 = new Test1[100];
Span<Test2> test2 = MemoryMarshal.Cast<Test1, Test2>(test1);

test1[1].X = 1;
test1[1].Y = 2;

Console.WriteLine(test1[1]); // Prints X=1, Y=2

test2[0].Z = 10; // Actually sets test1[1].X.

Console.WriteLine(test1[1]); // Prints X=10, Y=2
Run Code Online (Sandbox Code Playgroud)