Учитывая этот по большей части надуманный пример:
ref struct RefStruct {
int _field;
ref int _refField;
void AssignRef() {
_refField = ref _field;
// CS8374 Cannot ref-assign '_field' to '_refField' because '_field' has a narrower escape scope than '_refField'.
}
}
В документах говорится, что:
Компилятор гарантирует, что ссылка, хранящаяся в поле ref, не пережить своего референта.
Но при каких обстоятельствах ссылка на частное _field
, хранящееся в _refField
, переживет референт?
Поле без ссылки существует до тех пор, пока существует экземпляр структуры, но поле ссылки может существовать до тех пор, пока существует область вызывающего объекта. Другими словами, обычные поля имеют ref-safe-контекст «члена функции», но ref-поля имеют ref-safe-контекст «контекста вызывающего абонента». Подробности смотрите в правилах здесь.
Другими словами, вы можете сделать это:
// in RefStruct...
public static ref int Foo() {
var s = new RefStruct();
return ref s._refField;
// the lifetime of s ends here! But _refField is still living!
}
Тогда Foo
можно вызвать так:
ref int foo = ref RefStruct.Foo();
Спасибо за пример. Технические характеристики, как всегда, очевидны, когда вы знаете ответ.
ref int evilVar = anInstanceOfStruct._refField;
кажется, оно могло вот так убежать.