fixed – příkaz (Referenční dokumentace jazyka C#)
Příkaz fixed zabrání systému uvolňování paměti v přemístění vyměnitelné proměnné. Příkaz fixed je povolen pouze v nezabezpečeném kontextu. Klíčové slovo můžete použít také fixed k vytvoření vyrovnávacích pamětí s pevnou velikostí.
Příkaz fixed nastaví ukazatel na spravovanou proměnnou a přisoudí ji během provádění příkazu. Ukazatele na pohyblivé spravované proměnné jsou užitečné pouze v fixed kontextu. Bez kontextu fixed by uvolňování paměti mohlo proměnné nepředvídatelně přemístit. Kompilátor jazyka C# umožňuje přiřadit ukazatel na spravovanou proměnnou pouze v fixed příkazu .
class Point
{
public int x;
public int y;
}
unsafe private static void ModifyFixedStorage()
{
// Variable pt is a managed variable, subject to garbage collection.
Point pt = new Point();
// Using fixed allows the address of pt members to be taken,
// and "pins" pt so that it is not relocated.
fixed (int* p = &pt.x)
{
*p = 1;
}
}
Ukazatel můžete inicializovat pomocí pole, řetězce, vyrovnávací paměti s pevnou velikostí nebo adresy proměnné. Následující příklad znázorňuje použití adres proměnných, polí a řetězců:
Point point = new Point();
double[] arr = { 0, 1.5, 2.3, 3.4, 4.0, 5.9 };
string str = "Hello World";
// The following two assignments are equivalent. Each assigns the address
// of the first element in array arr to pointer p.
// You can initialize a pointer by using an array.
fixed (double* p = arr) { /*...*/ }
// You can initialize a pointer by using the address of a variable.
fixed (double* p = &arr[0]) { /*...*/ }
// The following assignment initializes p by using a string.
fixed (char* p = str) { /*...*/ }
// The following assignment is not valid, because str[0] is a char,
// which is a value, not a variable.
//fixed (char* p = &str[0]) { /*...*/ }
Počínaje jazykem C# 7.3 funguje příkaz na dalších typech kromě polí, řetězců, vyrovnávacích pamětí s pevnou velikostí nebo fixed nespravovaných proměnných. Jakýkoli typ, který implementuje metodu s GetPinnableReference názvem , lze připnout. Musí GetPinnableReference vracet ref proměnnou nespravovaného typu. Typy .NET System.Span<T> a System.ReadOnlySpan<T> představené v .NET Core 2.0 tento vzor používají a lze je připnout. To je znázorněno v následujícím příkladu:
unsafe private static void FixedSpanExample()
{
int[] PascalsTriangle = {
1,
1, 1,
1, 2, 1,
1, 3, 3, 1,
1, 4, 6, 4, 1,
1, 5, 10, 10, 5, 1
};
Span<int> RowFive = new Span<int>(PascalsTriangle, 10, 5);
fixed (int* ptrToRow = RowFive)
{
// Sum the numbers 1,4,6,4,1
var sum = 0;
for (int i = 0; i < RowFive.Length; i++)
{
sum += *(ptrToRow + i);
}
Console.WriteLine(sum);
}
}
Pokud vytváříte typy, které by měly být součástí tohoto modelu, podívejte se na Span<T>.GetPinnableReference() příklad implementace vzoru.
V jednom příkazu lze inicializovat více ukazatelů, pokud jsou všechny stejného typu:
fixed (byte* ps = srcarray, pd = dstarray) {...}
Chcete-li inicializovat ukazatele různých typů, jednoduše vnořte fixed příkazy, jak je znázorněno v následujícím příkladu.
fixed (int* p1 = &point.x)
{
fixed (double* p2 = &arr[5])
{
// Do something with p1 and p2.
}
}
Po spuštění kódu v příkazu se odepnou všechny připnuté proměnné a budou podléhat uvolňování paměti. Proto na tyto proměnné neukašete fixed mimo příkaz . Proměnné deklarované v fixed příkazu jsou vymezeny na tento příkaz, což usnadňuje:
fixed (byte* ps = srcarray, pd = dstarray)
{
...
}
// ps and pd are no longer in scope here.
Ukazatele inicializované v fixed příkazy jsou proměnné jen pro čtení. Pokud chcete upravit hodnotu ukazatele, musíte deklarovat druhou proměnnou ukazatele a upravit ji. Proměnnou deklarovanou v fixed příkazu nelze upravit:
fixed (byte* ps = srcarray, pd = dstarray)
{
byte* pSourceCopy = ps;
pSourceCopy++; // point to the next element.
ps++; // invalid: cannot modify ps, as it is declared in the fixed statement.
}
Paměť můžete přidělit do zásobníku, kde není předmětem uvolňování paměti, a proto není nutné ji připnout. K tomu použijte stackalloc výraz.
specifikace jazyka C#
Další informace najdete v oddílu s pevným příkazem specifikace jazyka C#.