Fixed statement
Motivation
GC may move a managed object around during runtime, so pointing to its address is not reliable since the address possibly changes all the time. So fixed
is to tell the GC not moving the object around.
cs
Person person = new();
unsafe
{
// get address of a field and assign it to a new pointer
fixed (int* ptr = &person.Age)
{
// dereferencing, in which returns the variable and assign new value
*ptr = 123;
}
Console.WriteLine(person.Age);
}
class Person { public int Age; }
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Managed and Unmanaged
- All enums are unmanaged
- All pointers are unmanaged
- All primitive types are unmanaged.
- User defined struct containing no managed field are unmanaged
When to use fixed
?
cs
class K { public int k; }
struct C
{
public int instanceMember;
public readonly static int shared;
public const int con = 0;
unsafe void M(int j, K k)
{
fixed (int* p = &j) { } // CS0213
fixed (int* p = &k.k) { }
int local = 0;
fixed (int* p = &local) { } // CS0213
int[] localArray = [];
fixed (int* p = localArray) fixed (int* pp = p) { } // CS8385
string localString = "abc";
fixed (char* p = localString) fixed (char* pp = p) { } // CS8385
K kk = new();
fixed (int* p = &kk.k) { }
fixed (int* p = &this.instanceMember) { }
fixed (int* p = &C.shared) { }
fixed (int* p = &C.con) { } // CS0211
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
j
lives inside the method only, and it's unmanaged so compiler yells.k
as a reference type and managed object, can be fixed.- local unmanaged can't be fixed
- local array is managed but
p
is already fixed in previous statement. - same as 5.
- local managed can be fixed
- static fields are kept alive until the program ends then GC collects, so it's managed.
- constants are simply values, not variable or field, there's no address for them.