But when we use unsafe pointers to memory addresses, that memory must not be moved. With fixed we can use pointers without interfering with GC.
Fixed example. This program must be compiled with unsafe code allowed. You can set this option in Visual Studio. It introduces the Transform method, which gets a random string.
Then The program uses the fixed statement to ensure that the garbage collector does not relocate the string data.
Info Inside the fixed statement is a block of code. The string data pointed to by the char* pointer will not be moved.
And This means we can manipulate that memory however we like. In the example, we increment the value of each character.
Finally The program adds 1 to each character in the string. It does this through pointer manipulation.
using System;
class Program
{
static void Main()
{
Console.WriteLine(Transform());
Console.WriteLine(Transform());
Console.WriteLine(Transform());
}
unsafe static string Transform()
{
// Get random string.
string value = System.IO.Path.GetRandomFileName();
// Use fixed statement on a char pointer.// ... The pointer now points to memory that won't be moved.
fixed (char* pointer = value)
{
// Add one to each of the characters.
for (int i = 0; pointer[i] != '\0'; ++i)
{
pointer[i]++;
}
// Return the mutated string.
return new string(pointer);
}
}
}61c4eu6h/zt1
ctqqu62e/r2v
gbekvhn6/xwq
Fixed buffer. The fixed modifier describes a buffer of constant size in an unsafe context in a struct. We use this memory as an array. This can help with performance.
using System;
unsafe struct FixedBufferExample
{
public fixed int _buffer[1024]; // This is a fixed buffer.
}
class Program
{
static FixedBufferExample _fixedBufferExample; // Reference to struct.
static void Main()
{
// Store values in the fixed buffer.// ... The load the values from the fixed buffer.
Store();
Load();
}
unsafe static void Store()
{
// Put the fixed buffer in unmovable memory.// ... Then assign some elements.
fixed (int* buffer = _fixedBufferExample._buffer)
{
buffer[0] = 1;
buffer[99] = 2;
buffer[1023] = 3;
}
}
unsafe static void Load()
{
// Put in unmovable memory.// ... Then load some values from the memory.
fixed (int* buffer = _fixedBufferExample._buffer)
{
Console.WriteLine(buffer[0]);
Console.WriteLine(buffer[99]);
Console.WriteLine(buffer[1023]);
}
}
}1
2
3
Fixed buffer, performance. The fixed buffer eliminates the need of many array bounds checks. But the overhead of changing the memory to an unmovable address often hurts performance.
Info A fixed buffer could be faster on long-running computations that are heavily numerical.
Tip As always, when improving performance, please set up benchmarks and only accept changes that result in an improvement.
Fixed statement, performance. There is a small cost to using the fixed statement. So it will only help on operations that spend significant amounts of time in unsafe code.
Fixed, warning. Optimizing with the fixed statement and pointer manipulation is often trial-and-error. It may make C# programs slower due to the transition from movable to fixed memory.
Thus If you are optimizing, make sure to benchmark all the unsafe changes you make.
A summary. Fixed is used with array elements, integer fields, and any data that is classified as movable—meaning it could be moved in memory during GC. This is a complex optimization.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Mar 24, 2023 (edit).