ref для переменных, а не параметров в функциях - PullRequest
17 голосов
/ 07 февраля 2011

Предположим, у меня есть класс Person, и у меня есть следующее:

Person A = new Person("Tom");
Person B = A;

Есть ли способ, которым я могу изменить его так, чтобы, если я назначу новый Person для B, B = new Person("Harry"), A, тоже будет ссылаться на тот же экземпляр? Я знаю, что вы можете сделать это в параметре ref в функции.

Ответы [ 3 ]

36 голосов
/ 07 февраля 2011

Функция, которую вы хотите, называется ref refals, и она не поддерживается в C #.

CLR поддерживает генерацию кода, содержащего локальные ссылки, и несколько лет назад я написал экспериментальную версию C #, в которой была нужная вам функция, просто чтобы посмотреть, будет ли она работать. Вы можете сделать что-то вроде:

Person a = whatever;
ref Person b = ref a;

и тогда, как вы говорите, изменения в "b" изменили бы содержимое "a". Две переменные становятся псевдонимами для одного и того же места хранения.

Хотя это была приятная небольшая функция и работала хорошо, мы решили не использовать ее для C #. Вполне возможно, что это все еще может произойти в гипотетической будущей версии языка, но я не буду в восторге от этого в ожидании; это, вероятно, не произойдет.

(Помните, что все размышления Эрика о гипотетических будущих версиях любого продукта Microsoft предназначены только для развлекательных целей.)

4 голосов
/ 07 февраля 2011

Нет, это невозможно в безопасном коде (за пределами ref параметров функции). В небезопасном коде вы можете использовать указатели для достижения этой цели, но я не думаю, что это хорошая идея.

A содержит ссылку на «Том» в качестве значения. Вам понадобится ссылка на 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. Если вы перенесете это в C #, вам понадобится ссылка на локальную переменную. И они доступны только в виде ref параметров функции. Это позволяет избежать некоторых проблем со временем жизни, поскольку ссылка на локальную переменную не может безопасно пережить эту локальную переменную.

Если это не частные переменные, вы можете сделать B свойством, которое изменяет A в установщике.

Person B{get{return A;} set{A=value;}}
2 голосов
/ 07 февраля 2011

Прямого способа сделать это не существует.

Вы можете использовать подход с исходным кодом, например:

A = B = new Person("Harry")

Или использовать универсальный тип.Что-то вроде:

var A = new ReferenceHolder<Person> (new Person("Tom")); 
var B = A;

В C # вы также можете использовать указатель (так что в основном это тип ref), но такой подход не проверяется статически и не предлагается.

...