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), но этот подход не является статически проверкой и не предлагается.