将可为null的数组复制到相同基类型的不可为null数组的有效方法
本文关键字:null 数组 类型 方法 基类 有效 复制 | 更新日期: 2023-09-27 18:25:17
有没有一种有效的方法可以将一个可为null的数组(比如byte?[]
)复制到一个不可为null(比如byte[]
)的数组,前提是保证源数组没有任何可为null值(如果有,可以抛出异常)?显然,我可以在索引上循环并单独复制每个元素。
这不起作用。它进行编译,但在运行时抛出一个ArrayTypeMismatchException
。
byte?[] sourceNullable = new byte?[]{1,2,3};
byte[] destNonNullable = new byte[3];
Array.Copy(sourceNullable,destNonNullable,3);
这会起作用,但我正在寻找";"更好";
for(int i=0;i<3;i++) {
destNonNullable[i] = sourceNullable[i] ?? 0;
}
我愿意接受这个答案:显式循环出了什么问题?为什么要浪费时间优化它?:)
编辑:我试着使用Linq风格的Cast<>()
,但速度慢得多。我的代码中的时间摘要如下:
对于环路=585 ms
Linq Cast=3626 ms
输入的image
文件是一个稀疏数组,其中填充了一些null。
uint rowsize = 16;
Stopwatch sw = new Stopwatch();
sw.Start();
for (UInt32 address = start & 0xFFFFFFF0; address <= last; address += rowsize)
{
Int32 imageOffset = (Int32)(address - start);
Int32 maxRowLen = (int)rowsize;
if (maxRowLen + imageOffset > image.Length) maxRowLen = (image.Length - imageOffset);
if (maxRowLen == 0) throw new Exception("this should not happen");
int ptr = 0;
while (ptr < maxRowLen)
{
while (ptr < maxRowLen && image[imageOffset + ptr] == null) ptr++;
int startOffset = ptr;
while (ptr < maxRowLen && image[imageOffset + ptr] != null) ptr++;
int stopOffset = ptr;
if (startOffset < maxRowLen)
{
#if false
int n = stopOffset - startOffset;
byte[] subdata = new byte[n];
for (int i = 0; i < n; i++)
{
subdata[i] = image[imageOffset + startOffset + i] ?? 0;
}
#else
byte[] subdata = image.Skip(imageOffset + startOffset).Take(stopOffset - startOffset).Cast<byte>().ToArray();
#endif
IntelHexRecord rec = new IntelHexRecord((uint)(address + startOffset), subdata);
records.Add(rec);
}
}
}
sw.Stop();
Console.WriteLine("elapsed: {0} ms", sw.ElapsedMilliseconds);
您可以使用LINQ,如下所示:
byte[] destNonNullable = sourceNullable.Cast<byte>().ToArray();
然而,这并不比你正在做的快。如果你需要一种更快的方法来复制编译时已知的固定数量的字节,你可以消除循环开销,这并没有那么大,但如果你必须挤出最后一个CPU周期,它应该会起作用:
byte[] destNonNullable = new[] {
sourceNullable[0].Value
, sourceNullable[1].Value
, sourceNullable[2].Value
};
您还可以通过展开循环来减少开销。例如,如果你知道你想复制的字节数可以被四整除,你可以这样做:
Debug.Assert(N % 4 == 0); // Otherwise, the loop below wouldn't stop
for (int i = 0 ; i != N ; i += 4) {
destNonNullable[i] = sourceNullable[i].Value;
destNonNullable[i+1] = sourceNullable[i+1].Value;
destNonNullable[i+2] = sourceNullable[i+2].Value;
destNonNullable[i+3] = sourceNullable[i+3].Value;
}