Почему при передачи параметра в функцию с модификатором ref необходимо использовать fixed для получения указателя?

С функцией Main все понятно, все переменные будут помещены в стек и поэтому не надо использовать fixed.

При вызове функции boo, будет передана ссылка на объект типа T (T - class), в свою очередь которая будет передана передана скорей всего через стек, поэтому так же не надо использовать fixed. (При использовании fixed в методе boo, компилятор выдает ошибку о том что объект уже закреплен.)

Возникает вопрос, почему в функции foo необходимо использовать fixed, ведь здесь не происходит перемещение объекта в кучу.

class Program
{
    private static unsafe void Main()
    {
        T obj = new T();
        T* objPtr = &obj;
        boo(obj);
        foo(ref obj);
    }
        
    private static unsafe void boo(T t)
    {
        T* adr = &t;
        ...
    }
        
    private static unsafe void foo(ref T t)
    {
        fixed(T* address = &t)
        {
          ...
        }
    }
}

class T
{
    public bool IsAlive;
}

Почему так происходит?


Ответы (1 шт):

Автор решения: rotabor

Возможно, что в случае с ref семантика fixed несколько другая - чтобы переменная не была изменена вне, так как перемещение объекта и замена объекта - по сути изменение ссылки на объект в переменной.

    object o = new();
    Task.Run(() => foo(ref o));
    ...
    object o = new(); // стрёмно

    private static unsafe void foo(ref T t)
    {
        fixed(T* address = &t)
        {
          ...
        }
    }
→ Ссылка