У меня есть куча методов, которые принимают WPF WriteableBitmap
и читают с его BackBuffer
напрямую, используя небезопасный код.
Не совсем ясно, следует ли использовать GC.KeepAlive
всякий раз, когда я делаю что-то вроде этого:
int MyMethod(WriteableBitmap bmp)
{
return DoUnsafeWork(bmp.BackBuffer);
}
С одной стороны, остается ссылка на bmp
на стек MyMethod
. С другой стороны, похоже, что он полагается на детали реализации - это может скомпилировать хвостовой вызов, например, не содержать ссылки на bmp
, когда вводится момент DoUnsafeWork
.
Аналогично, представьте себе следующий гипотетический код:
int MyMethod()
{
WriteableBitmap bmp1 = getABitmap();
var ptr = bmp.BackBuffer;
WriteableBitmap bmp2 = getABitmap();
return DoUnsafeWork(ptr, bmp2);
}
В теории ссылка на bmp1
остается в стеке до тех пор, пока метод не вернется, но опять же, похоже, используется деталь реализации. Разумеется, компилятор может объединить bmp1
и bmp2
, потому что они никогда не живут одновременно, и даже если компилятор никогда не делает этого, JITter все еще может и, возможно, делает это (например, сохраняя их как в тот же регистр, первый, затем другой).
Итак, в общем: следует ли полагаться на локальные/аргументы, являющиеся действительными ссылками на объект, или я всегда должен использовать GC.KeepAlive
для гарантии правильности?
Это особенно озадачивает, так как, по-видимому, FxCop считает, что GC.KeepAlive всегда плох.