Синтаксис оператора
fixed
таков:
fixed
(тип* указатель
=
выражение) оператор
Как сказано выше, этот оператор говорит GC, чтобы тот не трогал заданную переменную. Заметьте:
выражение
— любое выражение, результатом которого является указатель на
тип,
а словом
оператор
обозначен блок кода, к которому применима фиксация переменной. Вот простой пример.
using System;
class Foo {
public int x; }
class FixedlApp {
unsafe static void SetFooValue(int* x)
{
Console.WriteLineC'Dereferenced pointer to modify foo.x"); *x = 42; }
unsafe static void Main() {
// Создаем экземпляр структуры.
Console.WriteLine("Creating the Foo class");
Foo foo = new Foo();
Console.WriteLineC'foo.x intialized to {0}", foo.x);
// Оператор fixed фиксирует объект foo в пределах // включающего его составного оператора. Console.Writel_ine("Setting pointer to foo.x"); // Присвоить Foo* адрес объекта foo. fixed(int* f = &foo.x) <
Console.WriteLine("Calling SetFooValue passing " + "pointer to foo.x");
SetFooValue(f); >
// Убедимся, что мы действительно изменили член через
// указатель на него.
Console.WriteLine("After return from " +
"SetFooValue, foo.x = {0}", foo.x); } >
Этот код создает экземпляр класса
Foo
и фиксирует его оператором
fixed,
присваивая адрес его первого члена переменной типа
int*
(этот тип требуется методу
SetFooValue).
Заметьте, что оператор
fixed
включает именно тот код, на котором отразятся изменения при сдвиге объекта
Foo
сборщиком мусора. Это тонкий, но важный вопрос, касающийся больших и дольше исполняемых блоков кода, для которых вы хотите свести к минимуму время, в течение которого объект будет зафиксирован. В результате компиляции и запуска этого кода вы получите:
Creating the Foo class foo.x intialized to 0
\
Setting pointer to foo.x Calling SetFooValue passing pointer to foo.x Dereferenced pointer to modify foo.x After return from SetFooValue, foo.x = 42