HOWTO · Csharp

如何在 C# 中初始化字节数组

了解如何在 C# 中创建特定长度的字节数组、设置其值以及复制原始字节。

本页内容

C# 的 byte[] 存储 0 到 255 之间的字节值。使用 new byte[length] 创建元素最初包含零的数组,或者在已知值时使用数组初始化器。循环、Array.Fill 和 LINQ 可以分配重复或计算出的值;Buffer.BlockCopy 用于复制已经存储在数组中的字节。

以固定长度或显式值创建字节数组

要创建固定大小的 byte[],请将其长度传递给 new byte[length]。运行时会将每个元素初始化为零。当你预先知道这些值时,请改为将它们写入初始化器中。当每个值取决于其索引或另一个计算时,循环很有用。

下面的声明并排展示了两种常见形式。第一种保留四个位置,第二种直接列出三个字节值。然后循环按顺序访问每个位置,并根据其索引存储一个值。Length 提供位置的数量,因此当你更改请求的大小时,相同的循环形式可以适应。最后几行打印两个数组,以便你可以比较每种形式产生的值。

using System;

class Program
{
    static void Main()
    {
        byte[] values = new byte[4];
        byte[] explicitValues = { 0x10, 0x20, 0x30 };

        for (int i = 0; i < values.Length; i++)
        {
            values[i] = (byte)(i + 1);
        }

        Console.WriteLine(string.Join(", ", values));
        Console.WriteLine(string.Join(", ", explicitValues));
    }
}
1, 2, 3, 4
16, 32, 48

对于第一个数组,循环存储 1、2、3 和 4。显式初始化器创建一个单独的数组,其中包含列出的十六进制字节值。

将每个元素设置为相同的值

当项目的目标框架提供 Array.Fill 时,请使用它。它将一个字节值分配给指定数组中的每个元素。如果该 API 在项目中不可用,则对数组的 Length 使用 for 循环可提供相同的赋值。

using System;

class Program
{
    static void Main()
    {
        byte[] buffer = new byte[4];
        Array.Fill(buffer, (byte)255);
        Console.WriteLine(string.Join(", ", buffer));
    }
}
255, 255, 255, 255

强制转换使该值的类型显式。字节可以容纳 0 到 255 之间的值。

使用 LINQ 从重复值创建数组

Enumerable.Repeat 生成一个包含某个值的序列,该值出现请求的次数。调用 ToArray 将该序列具体化为 byte[]。该示例导入了 System.Linq,它提供了这两个方法。

using System;
using System.Linq;

class Program
{
    static void Main()
    {
        byte value = 42;
        int length = 5;
        byte[] values = Enumerable.Repeat(value, length).ToArray();
        Console.WriteLine(string.Join(", ", values));
    }
}
42, 42, 42, 42, 42

当新数组应自始至终包含相同的值时,这种方法具有可读性。当你已经有一个要更新的数组时,请使用 Array.Fill。

使用 Buffer.BlockCopy 复制原始字节

Buffer.BlockCopy 在元素类型为基元类型的数组之间复制原始字节,例如 byte[] 或 int[]。它的源偏移和目标偏移以及它的 count 都以字节为单位测量,而不是以数组元素为单位。确保源范围和目标范围有足够的空间进行请求的复制。它不会生成或填充一般值;对于该任务,请使用循环或 Array.Fill。

此示例将源字节数组中的四个字节复制到从字节偏移一开始的目标数组中。

using System;

class Program
{
    static void Main()
    {
        byte[] source = { 10, 20, 30, 40 };
        byte[] destination = new byte[6];

        Buffer.BlockCopy(source, 0, destination, 1, source.Length);
        Console.WriteLine(string.Join(", ", destination));
    }
}
0, 10, 20, 30, 40, 0

从较大的数值数组复制字节时,复制计数和偏移仍然使用字节。例如,这将两个 int 值中的前四个字节复制到一个四字节的目标中:

using System;

class Program
{
    static void Main()
    {
        int[] numbers = { 0x01020304, 0x05060708 };
        byte[] bytes = new byte[4];

        Buffer.BlockCopy(numbers, 0, bytes, 0, bytes.Length);
        Console.WriteLine(string.Join(", ", bytes));
    }
}

数值数组示例与平台相关:每个 int 中字节的顺序取决于平台的表示形式。在提供的环境中,此示例生成了 4, 3, 2, 1;该观察到的顺序特定于平台的整数字节表示形式,并不普遍。从 byte[] 复制可避免这种解释,因为其元素已经是字节。

选择一种初始化方法

当你需要一个用零初始化的固定大小数组时,请使用 new byte[length],对于一小列已知值,请使用初始化器。对于按位置计算的值,请使用循环;对于为现有数组分配一个值,请使用 Array.Fill;或者使用 Enumerable.Repeat(...).ToArray() 通过 LINQ 构建重复值数组。当数据已经作为原始字节存在于数组中并且需要复制时,请选择 Buffer.BlockCopy。