You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何在C#中显式强制转换sbyte[]/byte[]为bool[]、char[]为short[]/ushort[]?

C#中数组类型的显式强制转换问题解答

咱们先逐个解决你提到的两个数组类型转换问题,再聊聊你说的CIL代码和C#写法的差异:

一、sbyte[]/byte[] 能否转换为 bool[]?

在C#里,不能直接通过显式强制转换实现这两种数组的类型转换。虽然从底层内存布局来看,CLR里bool类型是用1字节存储的(和sbyte/byte的大小一致),但C#作为强类型语言,会严格检查数组的类型安全性——bool[]sbyte[]/byte[]是完全不同的数组类型,编译器不允许直接的类型转换。

你提到的CIL代码stelem Type sbyte (ldloc pArray) ldc_i4 1 ldc_i4 0能直接操作bool[],是因为CIL是更底层的中间语言,它可以绕过C#的类型安全检查,直接对数组的内存进行操作。但C#编译器不会允许你写类似的直接转换代码,比如你尝试的(sbyte[])pArray[1] = 1;不仅语法错误,本质上也违背了C#的类型规则。

如果要实现类似CIL的内存级操作,你可以用C#的**不安全代码(Unsafe)**来绕过类型检查,不过这种方式要谨慎使用,因为它会打破类型安全:

unsafe
{
    bool[] pArray = new bool[5];
    fixed (bool* boolPtr = pArray)
    {
        // 将bool数组的指针强制转换为sbyte指针
        sbyte* sbytePtr = (sbyte*)boolPtr;
        sbytePtr[1] = 1; // 对应pArray[1] = true
    }
}

另外,也可以用Buffer.BlockCopy来实现内存复制,这种方式更安全:

sbyte[] sbyteArray = new sbyte[] {0, 1, 0};
bool[] boolArray = new bool[sbyteArray.Length];
Buffer.BlockCopy(sbyteArray, 0, boolArray, 0, sbyteArray.Length);

二、char[] 能否转换为 short[]/ushort[]?

同样,C#也不允许直接显式强制转换char[]short[]/ushort[]。虽然char在CLR里是UTF-16编码的16位值,和short/ushort的内存大小一致,但它们的数组类型依然是独立的,值类型数组不支持协变转换。

要实现两者的内存级转换,同样可以用Buffer.BlockCopy或者不安全代码:

用Buffer.BlockCopy的安全方式:

char[] charArray = {'a', 'b', 'c'};
short[] shortArray = new short[charArray.Length];
// 复制char数组的内存到short数组
Buffer.BlockCopy(charArray, 0, shortArray, 0, charArray.Length * sizeof(char));

用Unsafe的直接内存操作:

unsafe
{
    char[] charArray = {'x', 'y'};
    fixed (char* charPtr = charArray)
    {
        short* shortPtr = (short*)charPtr;
        shortPtr[0] = 0x4241; // 对应charArray[0]会变成'A'(注意字节序,CLR是小端存储)
    }
}

总结一下

C#的类型安全机制限制了值类型数组之间的直接强制转换,但你可以通过Buffer.BlockCopy(安全)或者不安全代码(底层操作)来实现类似CIL的内存级操作。而你尝试的写法之所以不被允许,是因为它既不符合C#的语法规则,也违反了C#的类型安全设计。

内容的提问来源于stack exchange,提问作者Nick

火山引擎 最新活动