У вас есть распространенное заблуждение новичка о том, как работают переменные ссылочного типа в C #.
Давайте рассмотрим более простой пример:
class F1
{
static int x = 0;
public static int Start()
{
x = 1;
return x;
}
public static void Stop()
{
x = 0;
}
}
class F2
{
int y;
void DoIt()
{
this.y = F1.Start();
F1.Stop();
Console.WriteLine(this.y);
}
}
Предположим, мы вызываем DoIt дляэкземпляр F2.Какое значение this.y
?
Трассировка в результате действия программы:
- F1.x начинается с нуля.
- F2.DoIt вызывает F1.Start ()
- F1.x становится 1
- F1.Start () возвращает 1
- F2.y становится 1
- F2.DoIt вызывает F1.Stop ()
- F1.x становится 0
F2.y по-прежнему 1. Изменение F2.x ничего не изменило в F2.y.Это совершенно другая переменная.Мы не создали никакой магической связи, которая говорила бы: «Когда вы читаете F2.y, действительно читаете текущее значение F2.x».
То же самое верно и в вашей программе.Мы можем изменить его на ссылочные типы, и ничего не изменится:
class F1
{
public static F1 x = null;
public static F1 Start()
{
x = new F1();
return x;
}
public static void Stop()
{
x = null;
}
}
class F2
{
F1 y;
void DoIt()
{
this.y = F1.Start();
F1.Stop();
Console.WriteLine(this.y == null); // false
}
}
Что происходит?То же самое.
- F1.x начинается с нуля.
- F2.DoIt вызывает F1.Start ()
- F1.x становится ссылкой на действительный объект
- F1.Start () возвращает ссылку на действительный объект
- F2.y становится ссылкой на действительный объект
- F2.DoIt вызывает F1.Stop ()
- F1.x становится нулевым
Что такое F2.y? Все еще ссылка на действительный объект .F2.y был никогда ссылкой на F1.x.Они оба были ссылкой на один и тот же действительный объект. Ссылки являются значениями, как целые числа .
Теперь, если вы хотите сделать псевдоним для переменной, C # 7 позволяет вам сделать это:
class F1
{
static int x = 0;
public static ref int Start()
{
x = 1;
return ref x;
}
public static void Stop()
{
x = 0;
}
}
class F2
{
void DoIt()
{
ref int y = ref F1.Start();
F1.Stop();
Console.WriteLine(y); // 0
}
}
* ref
означает, что локальная переменная y является псевдонимом переменной F1.x , поэтому, когда мы изменяем F2.x
, мы также меняем y
, потому что их всего два имена для той же переменной ;они псевдоним .
Обратите внимание, что псевдоним переменной не имеет ничего общего с типом переменной .Вы можете сделать псевдоним для переменной int, вы можете сделать псевдоним для переменной объекта, что угодно.Переменная с псевдонимом и локальный псевдоним должны иметь точно такой же тип (упражнение: почему?), Но этот тип может быть любым, чем вы хотите.
Хотя правило таково: переменная с псевдонимом может быть любой переменной;переменная псевдонимов может быть только локальным или формальным параметром .Например, нет способа создать поле ref int.Обратите внимание, что ref int y
является локальным , а не полем .
Возвращение переменных-псевдонимов - это расширенная функция, которую мы много лет обсуждали, правильно ли было добавлятьв C #. Вы не должны использовать эту функцию, пока у вас нет глубокого и глубокого понимания семантики ссылок в C # .