Я читал документацию по C # 7.2 здесь , и я столкнулся с этим в отношении ref readonly
:
Компилятор обеспечивает, что вызывающая сторона не может изменить ссылку,Попытки присвоить значение напрямую генерируют ошибку во время компиляции.Однако компилятор не может знать, изменяет ли какой-либо метод-член состояние структуры.Чтобы гарантировать, что объект не был изменен, компилятор создает копию и вызывает ссылки на члены, используя эту копию.Любые изменения касаются этой защитной копии.
Это создало некоторую путаницу для меня (и, возможно, некоторых других), поэтому я хотел бы уточнить поведение сейчас.Предположим, у меня есть структура, определенная следующим образом:
public struct Point3D
{
private static Point3D origin = new Point3D(0,0,0);
public static ref readonly Point3D Origin => ref origin;
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public static void ChangeOrigin(int x = 0, int y = 0, int z = 0)
{
origin = new Point3D(x, y, z);
}
}
Теперь предположим, что я использовал ref readonly
для получения Point3D.Origin
и изменил ее:
ref readonly var origin = ref Point3D.Origin;
var originValue = Point3D.Origin;
Point3D.ChangeOrigin(1, 1, 1);
Console.WriteLine("Origin is: ({0}, {1}, {2})", origin.X, origin.Y, origin.Z);
Console.WriteLine("Origin is: ({0}, {1}, {2})", originValue.X, originValue.Y, originValue.Z);
Результат выполнения этого кодаэто:
Origin is: (1, 1, 1)
Origin is: (0, 0, 0)
Это ожидается.Значение в origin
обновляется, когда я вызываю ChangeOrigin
, тогда как значение в originValue
копируется и, следовательно, не изменяется.Мой вопрос касается "защитной копии", упомянутой выше.Почему это необходимо?Значение в origin
не может быть изменено без вызова ошибок компилятора, и ссылка обновляется должным образом, когда Point3D.Origin
обновляется, поэтому, почему есть дополнительная копия объекта, которая из того, что я собрал, читая документацию,не обновляется?