Присвойте значение по ссылке члену класса по ссылке

Что-то меня смущает, и я надеюсь, что вы сможете прояснить ситуацию.

// This class assumes that T is definitively compatible to TheStruct
class ValueHolder<T> {
  T _value;
  TheStruct _structValue;

  void Test1() {
    _structValue = ref Unsafe<T, TheStruct>(ref _value); // ERROR: _structValue is not a by-ref value
    // _structValue = Unsafe<T, TheStruct>(ref _value); // WORKS: Copy from stack to heap
  }

  void Test2() {
    ref var structValue = ref _structValue;
    structValue = ref Unsafe.As<T, TheStruct>(ref _value); // WORKS: Why, and what implication does it have?
  }
}

Итак, мой вопрос в Test2: почему я могу назначить Unsafe.As в качестве ссылки при определении ref var structValue = ref _structValue;. И что еще более важно, какие последствия это будет иметь, если использовать это поверх _structValue = Unsafe<T, TheStruct>(ref _value);?

Спасибо за чтение, и я надеюсь, что вы сможете пролить свет на это. :)

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
ref var structValue = ref _structValue;
structValue = ref Unsafe.As<T, TheStruct>(ref _value); // WORKS: Why, and what implication does it have?

Почему я могу назначить Unsafe.As в качестве ссылки при определении ref var structValue = ссылка _structValue;

Потому что вы можете переназначить ссылку ref local на другую ссылку.

Надеюсь, этот пример прояснит ситуацию:

var foo = 42;
var bar = 1;

ref var refVar = ref foo;
refVar++; // as if we wrote foo++
Console.WriteLine(foo); // 43

refVar = ref bar; // at this point we detach refVar as alias for foo

refVar++; // as if we wrote bar++
Console.WriteLine(foo); // still 43
Console.WriteLine(bar); // 2

Итак, к вашему первоначальному вопросу:

ref var structValue = ref _structValue;
structValue = ref Unsafe.As<T, TheStruct>(ref _value); // WORKS: Why, and what implication does it have?

вторая строка не будет присваивать полю _structvalue ссылку, которая Unsafe.As возвращает. Он присвоит ссылку на локальную переменную structValue.

Поэтому, когда Test2 возвращается, вы фактически ничего не сделали с полем _structValue. В рабочей части Test1 вы фактически скопировали значение, которое было там в данный момент, из _value:

_structValue = Unsafe<T, TheStruct>(ref _value);

Будущие изменения _value не будут отражены в _structValue.

Возможно, вы захотите просмотреть ref-структуры, доступные в .NET 7, где вы можете иметь не только ref local переменные, но и ref fields такие как:

ref TheStruct _structValue;

Однако если бы вы сделали то, что хотели,

_structValue = ref Unsafe.As<T, TheStruct>(ref _value); 

компилятор выдаст эту ошибку:

CS8374 Cannot ref-assign 'Unsafe.As<T, TheStruct>(ref _value)' to '_structValue' because 'Unsafe.As<T, TheStruct>(ref _value)' has a narrower escape scope than '_structValue'.

что мне кажется немного странным, потому что это поле в той же структуре... но это, возможно, другой вопрос.

Я полностью осознаю это, что левая часть должна быть ref-переменной, если вы хотите присвоить ref-переменную, но вопрос в том, почему я могу это сделать: structValue = ref Unsafe.As<T, TheStruct>(ref _value); где structValue определяется как ref var structValue = ref _structValue;. Не перераспределяет ли Unsafe.As<,> внутреннюю память и не приведет ли такое присвоение ссылки к нарушению допустимой области возвращаемого значения ссылки Unsafe.As<,>??

Teneko 28.08.2024 21:31

Другой взгляд: когда Unsafe.As<,> ref назначается ref var structValue = ref _structValue;, не повредит ли это память по адресу _structValue, когда Test2 вернется? Так что же я в конечном итоге назначаю _structvalue? Тот же адрес _value, на который я перешёл Unsafe.As<T, TheStruct>(ref _value)?

Teneko 28.08.2024 21:32

@Teneko Я отредактировал свой ответ. во втором примере вы ничего не назначаете _structValue. Вы назначаете локальную переменную ref structValue.

Ivan Petrov 28.08.2024 22:59

Спасибо, теперь я понял. Последняя ошибка компилятора, о которой вы упомянули, была той ошибкой, которую я ожидал во втором примере. Ваш пример действительно был очень поучительным. Теперь я понимаю, что я просто заменяю адрес ссылки локальной ссылки, а не адрес ссылочного значения этой локальной ссылки.

Teneko 29.08.2024 00:08

Мне это также кажется несколько странным, но я думаю, что перегрузка Unsafe.As<,> не знает, ограничено ли значение по ссылке локальным или полем, поэтому она всегда ограничивает возвращаемое значение ref локальным.

Teneko 29.08.2024 00:12

Другие вопросы по теме