无论如何都要明确施放/强制
sbyte[]
或byte[]
到bool[]
char[]
到short[]
/ ushort[]
在CIL中,您经常会看到诸如
之类的内容stelem Type sbyte (ldloc pArray) ldc_i4 1 ldc_i4 0
正在执行pArray[1] = true
,其中pArray
是类型为bool[]
的一维数组。我想通过执行
(sbyte[])pArray[1] = 1;
不幸的是,C#编译器不允许这样做。
答案 0 :(得分:17)
未记录的技巧,自担风险:
(例如here和许多其他地方显示)
[StructLayout(LayoutKind.Explicit)]
public struct ConvSByteBool
{
[FieldOffset(0)]
public sbyte[] In;
[FieldOffset(0)]
public bool[] Out;
}
然后:
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
请注意,这个技巧与泛型有点不兼容。没有Conv<T, U>
!
当源和目标中的元素大小相同(sizeof(sbyte) == sizeof(bool)
)时,该技巧最有效。否则会有一些限制(在上面的链接问题中描述)。
答案 1 :(得分:9)
您可以使用the new Span<T>
and MemoryMarshal
types执行此操作。
请注意,这仅适用于最新版本的C#,您现在必须使用NuGet包来提供库,但这会发生变化。
例如,对于&#34;演员&#34;一个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'
此方法已记录在案,并且不会复制任何数据 - 并且它的性能也非常高(按设计)。
请注意,这也适用于结构:
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
另请注意,这可以让您做一些可疑的事情,例如:
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
答案 2 :(得分:1)
这只是部分答案。
哈克:
C#编译器和运行时完全不同意哪些数组类型可以相互转换(正如您在问题中暗示的那样)。因此,您可以通过System.Array
(或System.Object
或System.Collections.IEnumerable
等)来避免询问编译器并将强制转换推迟到运行时。
一个例子:
using System;
static class P
{
static void Main()
{
var a = new sbyte[] { -7, -3, 8, 11, };
var hack = (byte[])(Array)a;
Console.WriteLine(string.Join("\r\n", hack));
}
}
输出:
249 253 8 11
如果你要避免上面代码中的中间(Array)
,C#编译器会告诉你演员阵容是不可能的。
答案 3 :(得分:0)
您可以使用扩展方法,如下所示:
$.ajax({
type: 'post',
url: "https://gateway.watsonplatform.net/assistant/api/v1/workspaces/XXX...XXX/message?version=20XX-XX-XX",
data: "{ \"input\": {\"text\": \"Hello\"}} ",
headers : {'Content-Type' : 'application/json' },
u : { 'uname' : 'pwd' },
success:function(response)
{
console.log("Success!!");
},
error : function(xhr, status, error)
{
console.log("Status of error message" + status + "Error is" + error);
}
});
然后就这样使用它:
namespace ExtensionMethods
{
public static class ByteExt
{
public static bool ToBool(this byte b) => b != 0;
public static bool[] ToBoolArray(this byte[] bytes)
{
bool[] returnValues = new bool[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
returnValues[i] = bytes[i].ToBool();
return returnValues;
}
// Do same for sbyte
}
public static class CharExt
{
public static short[] ToBoolArray(this char[] chars)
{
short[] returnValues = new bool[chars.Length];
for (int i = 0; i < chars.Length; i++)
returnValues[0] = (short)chars[0];
return returnValues;
}
}
}
在C#8中,可能会出现所谓的“扩展所有内容”,您可以在其中定义自己的扩展转换,包括显式和隐式。
语法将是这样的:
byte[] myBytes = new[] {1, 2, 5};
bool[] myBools = myBytes.ToBoolArray();
可以像这样使用它:
public extension class ByteExt extends Byte[]
{
public static explicit operator bool[](byte[] bytes)
{
// Same implementation as before
}
}
答案 4 :(得分:-1)
使用Array.ConvertAll
如下:
// Input
sbyte[] sbyteArray = { 0, 1, 2, 0 };
byte[] byteArray = { 0, 1, 2, 0 };
// Result
bool[] boolArray1 = Array.ConvertAll(sbyteArray, (item) => Convert.ToBoolean(item));
bool[] boolArray2 = Array.ConvertAll(byteArray, (item) => Convert.ToBoolean(item));
// Input
char[] charArray = { 'A', 'B', 'C' };
// Result
short[] shortArray = Array.ConvertAll(charArray, (item) => Convert.ToInt16(item));
ushort[] ushortArray = Array.ConvertAll(charArray, (item) => Convert.ToUInt16(item));