#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结

时间:2023-02-27 07:56:50

前言

C#中有多维数组和交错数组

  • 多维数组:就是m×n的矩阵,m行n列
  • 交错数组:有m行,但是每一行不一定是n列

1.多维数组

C# 里的多维数组 (Multi-dimensional Array) 是这样的

byte[,] arr = new byte[10, 10];

案例

int row = 5;
int column = 5;
int[,] matrix = new int[row, column];
//初始化
for (int i = 0; i < row; i++)
{
    for (int j = 0; j < column; j++)
    {
        matrix[i, j] = (i + 1) * 10 + j + 1;
    }
}
//输出
Console.WriteLine("该二维数组有:{0}行{1}列!", matrix.GetLength(1), matrix.GetLength(1));
for (int i = 0; i < row; i++)
{
    for (int j = 0; j < column; j++)
    {
        Console.Write(matrix[i, j] + " ");
    }
    Console.Write('\n');
}

#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结

2.交错数组

C# 里的交错数组 (Jagged Array),就是数组里面套着数组

byte[][] arr = new byte[10][];

案例

int row = 5;
//交错数组空间的申请
int[][] matrix = new int[row][];
for (int i = 0; i < row; i++)
{
    matrix[i] = new int[i + 1];
}
//数据初始化
for (int i = 0; i < matrix.Length; i++)
{
    for (int j = 0; j < matrix[i].Length; j++)
    {
        matrix[i][j] = (i + 1) * 10 + j + 1;
    }
}
//数据输出
for (int i = 0; i < matrix.Length; i++)
{
    for (int j = 0; j < matrix[i].Length; j++)
    {
        Console.Write(matrix[i][j] + " ");
    }
    Console.Write('\n');
}


Console.ReadLine();

#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结

一、数组复制总结

定义一下常量,SIZE 表示数组大小,COUNT 表示等会要做拷贝测试的循环次数

//SIZE = 32 << 20  相当于 32的二进制数后面补20个0,相当于 32 * 2 ^ 20
const int COUNT = 32, SIZE = 32 << 20;

1.Array.Clone

在C#中,只要实现了 ICloneable 接口的对象,就有 Clone 方法

byte[] 
    dSource = new byte[SIZE],
    dTarget = new byte[SIZE];

var sw = Stopwatch.StartNew();
sw.Start();

for (var i = 0; i < COUNT; i++)
{
    dTarget = (byte[])dSource.Clone();
}

sw.Stop();
Console.WriteLine("Array.Clone: {0:N0} ticks, {1} ms", sw.ElapsedTicks, sw.ElapsedMilliseconds);

#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结

2.Linq

Linq的原理一个个元素遍历,再重新构造个新的数组

byte[]
    eSource = new byte[SIZE],
    eTarget = new byte[SIZE];

var sw1 = Stopwatch.StartNew();
sw1.Start();

eTarget = eSource.Select(x => x).ToArray();

sw1.Stop();
Console.WriteLine("Array.Clone: {0:N0} ticks, {1} ms", sw1.ElapsedTicks, sw1.ElapsedMilliseconds);

#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结

3.Array.Copy

//-------------------------------------3.Array.Copy----------------------------------------------------
byte[]
    cSource = new byte[SIZE],
    cTarget = new byte[SIZE];

var sw2 = Stopwatch.StartNew();
sw2.Start();

//Array.Copy(cSource, 0, cTarget, 0, SIZE);
Array.Copy(cSource, cTarget, SIZE);

sw2.Stop();
Console.WriteLine("Array.Copy: {0:N0} ticks, {1} ms", sw2.ElapsedTicks, sw2.ElapsedMilliseconds);

#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结

4.Buffer.BlockCopy

byte[]
    bSource = new byte[SIZE],
    bTarget = new byte[SIZE];

var sw3 = Stopwatch.StartNew();
sw3.Start();

Buffer.BlockCopy(bSource, 0, bTarget, 0, SIZE);

sw3.Stop();
Console.WriteLine("Buffer.BlockCopy: {0:N0} ticks, {1} ms", sw3.ElapsedTicks, sw3.ElapsedMilliseconds);

#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结

5.Buffer.MemoryCopy

使用这个方法需要开启非安全访问

第一步:在你需要启用不安全代码的项目上点击右键,然后选择编辑项目文件: #yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结 第二步:在你的项目文件的属性组中添加一行 <AllowUnsafeBlocks>true</AllowUnsafeBlocks>#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结

//-------------------------------------5.Buffer.MemoryCopy----------------------------------------------------

TestBufferMemoryCopy();
static unsafe void TestBufferMemoryCopy()
{
    byte[]
    fSource = new byte[SIZE],
    fTarget = new byte[SIZE];

    var sw4 = Stopwatch.StartNew();
    sw4.Start();

    fixed (byte* pSrc = fSource, pDest = fTarget)
    {
        for (int i = 0; i < COUNT; i++)
        {
            Buffer.MemoryCopy(pSrc, pDest, SIZE, SIZE);
        }
    }

    sw4.Stop();
    Console.WriteLine("Buffer.MemoryCopy: {0:N0} ticks, {1} ms", sw4.ElapsedTicks, sw4.ElapsedMilliseconds);
}

#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结

2、运行

性能测试结果如下 #yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-数组复制总结 可以看到Buffer.BlockCopy性能是最好的。