Как уже отмечали другие, вы не можете иметь поле типа "ref to variable". Однако, просто зная, что вы не можете сделать это, вероятно, неудовлетворительно; Вы, вероятно, также хотите знать, во-первых, почему нет, а во-вторых, как обойти это ограничение.
Причина в том, что есть только три возможности:
1) Запретить поля типа ref
2) Разрешить небезопасные поля типа ref
3) Не использовать пул временного хранилища для локальных переменных (он же «стек»)
Предположим, мы допустили поля типа ref. Тогда вы могли бы сделать
public ref int x;
void M()
{
int y = 123;
this.x = ref y;
}
и теперь y можно получить после завершения M
. Это означает, что либо мы находимся в случае (2) - доступ к this.x
завершится сбоем и ужасно погибнет, потому что хранилище для y больше не существует - либо мы находимся в случае (3), а локальный y
хранится в куче собранного мусора, а не во временном пуле памяти.
Нам нравится оптимизация, заключающаяся в том, что локальные переменные хранятся во временном пуле, даже если они передаются по ссылке, и мы ненавидим идею о том, что вы можете оставить вокруг себя бомбу замедленного действия, которая может привести к аварийному завершению работы вашей программы и ее смерти. Таким образом, первый вариант: нет ссылок.
Обратите внимание, что для локальных переменных, которые являются закрытыми переменными анонимных функций, мы выбираем option (3); эти локальные переменные не выделяются из временного пула.
Что тогда подводит нас ко второму вопросу: как вы справляетесь с этим? Если вы хотите, чтобы поле ref было причиной получения и установки другой переменной, это совершенно законно:
sealed class Ref<T>
{
private readonly Func<T> getter;
private readonly Action<T> setter;
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value { get { return getter(); } set { setter(value); } }
}
...
Ref<int> x;
void M()
{
int y = 123;
x = new Ref<int>(()=>y, z=>{y=z;});
x.Value = 456;
Console.WriteLine(y); // 456 -- setting x.Value changes y.
}
И вот, пожалуйста. y
хранится в куче gc, а x
- это объект, который может получить и установить y
.
Обратите внимание, что CLR поддерживает ref locals и ref return методы, а C # - нет. Возможно, гипотетическая будущая версия C # будет поддерживать эти функции; Я прототипировал его, и он хорошо работает. Тем не менее, это не очень высокий приоритет в списке приоритетов, поэтому мои надежды не оправдаются.
ОБНОВЛЕНИЕ: функция, упомянутая в предыдущем параграфе, была наконец реализована для реального в C # 7. Однако вы все еще не можете сохранить ссылку в поле.