该 fixed
语句可防止 垃圾回收器 重新定位可移动变量并声明指向该变量的指针。 固定或固定变量的地址在执行语句期间不会更改。 只能在相应的 fixed
语句内使用声明的指针。 声明的指针是只读的,无法修改:
unsafe
{
byte[] bytes = [1, 2, 3];
fixed (byte* pointerToFirst = bytes)
{
Console.WriteLine($"The address of the first array element: {(long)pointerToFirst:X}.");
Console.WriteLine($"The value of the first array element: {*pointerToFirst}.");
}
}
// Output is similar to:
// The address of the first array element: 2173F80B5C8.
// The value of the first array element: 1.
注释
只能在不安全的上下文中使用fixed
该语句。 必须使用 AllowUnsafeBlocks 编译器选项编译包含不安全块的代码。
可以按如下所示初始化声明的指针:
使用数组,如本文开头的示例所示。 初始化的指针包含第一个数组元素的地址。
使用变量的地址。 使用 地址
&
运算符,如以下示例所示:unsafe { int[] numbers = [10, 20, 30]; fixed (int* toFirst = &numbers[0], toLast = &numbers[^1]) { Console.WriteLine(toLast - toFirst); // output: 2 } }
对象字段是可固定的可移动变量的另一个示例。
当初始化的指针包含对象字段或数组元素的地址时,
fixed
该语句保证垃圾回收器在执行语句正文期间不会重新定位或释放包含的对象实例。使用实现名为 <
a0/a0> 的方法的类型实例。 该方法必须返回 ref
非托管类型的变量。 .NET 类型 System.Span<T> 并 System.ReadOnlySpan<T> 使用此模式。 可以固定跨度实例,如以下示例所示:unsafe { int[] numbers = [10, 20, 30, 40, 50]; Span<int> interior = numbers.AsSpan()[1..^1]; fixed (int* p = interior) { for (int i = 0; i < interior.Length; i++) { Console.Write(p[i]); } // output: 203040 } }
有关详细信息,请参阅 Span<T>.GetPinnableReference() API 参考。
使用字符串,如以下示例所示:
unsafe { var message = "Hello!"; fixed (char* p = message) { Console.WriteLine(*p); // output: H } }
使用 固定大小的缓冲区。
可以在堆栈上分配内存,其中不受垃圾回收的影响,因此不需要固定。 为此,请使用 stackalloc
表达式。
还可以使用 fixed
关键字声明 固定大小的缓冲区。
C# 语言规范
有关更多信息,请参阅 C# 语言规范的以下部分: