Ref для переменных, а не параметров в функциях
Предположим, что у меня есть класс Person
и имеют следующее:
Person A = new Person("Tom");
Person B = A;
Есть ли способ изменить его так, что если я назначу новый Person
на B
, B = new Person("Harry")
, A
будет ссылаться на тот же экземпляр тоже? Я знаю, что вы можете сделать это при назначении параметра ref
в функции.
Ответы
Ответ 1
ОБНОВЛЕНИЕ: описанная здесь функция была добавлена в С# 7.
Функция, которую вы хотите, называется "ref locals" и не поддерживается в С#.
CLR поддерживает генерацию кода, содержащего локальные ссылки, и несколько лет назад я написал экспериментальную версию С#, в которой была нужная вам функция, просто чтобы посмотреть, будет ли она работать. Вы можете сделать что-то вроде:
Person a = whatever;
ref Person b = ref a;
и тогда, как вы говорите, изменения в "b" изменили бы содержимое "a". Две переменные становятся псевдонимами для одного и того же места хранения.
Хотя это была приятная небольшая функция и работала хорошо, мы решили не использовать ее для С#. Вполне возможно, что это все еще может произойти в гипотетической будущей версии языка, но я не буду в восторге от этого в ожидании; это, вероятно, не произойдет.
(Помните, что все размышления Эрика о гипотетических будущих версиях любого продукта Microsoft предназначены только для развлекательных целей.)
Ответ 2
Нет, это невозможно в безопасном коде (помимо параметров функции ref
). В небезопасном коде вы можете использовать указатели для достижения этого, но я не думаю, что это хорошая идея.
A
содержит ссылку на "Tom" в качестве значения. Вам понадобится ссылка на A
, чтобы изменить там, где она указана.
Если мы рассмотрим аналогичный код на языке, который явно использует указатели вместо неявной обработки экземпляров классов в качестве ссылок:
Person* A=new Person("Tom");
Person* B=A;
B=new Person("Harry");//Changes only B
Person** C=&A;
(*C)=new Person("John");//Now A changes
Для изменения A
вам нужен указатель на указатель. Если вы переведете это на С#, вам понадобится ссылка на локальную переменную. И они доступны только в виде параметров функции ref
. Это позволяет избежать некоторых проблем с продолжительностью жизни, поскольку ссылка на локальную переменную не может безопасно пережить эту локальную переменную.
Если это не частные переменные, вы можете сделать свойство B, которое модифицирует A в установщике.
Person B{get{return A;} set{A=value;}}
Ответ 3
Нет прямого способа сделать это.
Вы можете использовать подход с исходным кодом, например:
A = B = new Person("Harry")
Или используйте общий тип. Что-то вроде:
var A = new ReferenceHolder<Person> (new Person("Tom"));
var B = A;
В С# вы также можете использовать указатель (в основном тип ref), но этот подход не является статически проверкой и не предлагается.