2015-09-28 3 views
1

Я знаю, что классы ВСЕГДА передаются по ссылке иначе, чем структуры, переданные по значению.Я объявила переменную для класса и передала ее в метод для ее создания, но исходная переменная остается неизменной

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

public MainWindow() 
{ 
    InitializeComponent();  
    Func(myPath); 

    if (myPath == null) 
     MessageBox.Show("AAAARGH"); 
} 

Path myPath; 

private void Func(Path p) 
{ 
    if (p == null) 
     p = new Path(); 
} 

Таким образом, после вызова функции, я бы ожидать myPath не быть null больше, так как он был инициализирован в Func(), но это не так.

Я работаю над глобальным значением. Это что-то меняет?

+0

Передача по ссылке вы все еще не может изменить, где что ссылка указывает на без ref ключевое слово. Вы можете изменить свойства этого объекта, но вы не можете создать новый объект и сохранить его для вызывающего. –

+0

это действительно плохой дизайн. Почему бы просто не использовать 'myPath' напрямую? Кроме того, что бы вы ни делали, это не относится к коду. Создайте правильный ViewModel. –

+0

Я работаю над многолучевым холстом. Эта же функция может работать как на новых путях, так и на путях, выбранных пользователем с помощью мыши. Вот почему у меня есть myPath, который обозначает mouseSelectedPath. Это говорит, что вы правы. Я переработаю свой код, пытаясь не использовать глобальный путь. Еще одна вещь: почему бы не работать над кодом? Это довольно сложная программа, поэтому я не могу поместить все в файл xaml. – Patrick

ответ

0

Когда вы изначально называют Func(), myPath и p ссылка тот же экземпляр Path. Однако myPath и p остаются двумя отдельными ссылками, которые указывают на тот же самый экземпляр.

То есть, пока следующий код не работает:

p = new Path(); 

После этого p ссылается на новый экземпляр Path, который отделен от оригинала. Изменение свойств в экземпляре, которое относится к p, не будет отражено в примере, на который ссылается myPath.

Другими словами:

private void Func(Path p) // p is a separate reference, referencing same Path as myPath 
{ 
    if (p == null)   // p still references same Path as myPath 
     p = new Path(); // now p references a new instance of Path, separate from myPath 
} 

Вы можете использовать ref (или out) ключевое слово, так что ссылка идентифицируется myPath сама передается «по ссылке», эффект которого является то, что myPath и p являются одна ссылка.

Затем, когда вы создаете новый экземпляр Path внутри вашего метода, myPath и p остаются единственной ссылкой, указывающей на новый экземпляр.(Ваш оригинальный экземпляр остается там в памяти где-то, но ничего не ссылаться на него больше.)

Path myPath = null; 

private void Func(ref Path p) // p is same reference as myPath 
{ 
    if (p == null) 
     p = new Path();  // p and myPath are still same reference, 
           // now referencing a new instance of Path 
} 

Или:

Path myPath; 

private void Func(out Path p) // p is same reference as myPath 
{ 
    if (p == null)  
     p = new Path();  // p and myPath are still same reference, 
           // now referencing a new instance of Path 
} 
+0

Спасибо миллион очень ясно и лаконично. – Patrick

+0

Неправильно. «Экземпляр класса» не является значением в C# и не может быть «передан». Когда вы создаете экземпляр, вы получаете * reference * (значение ссылочного типа), и вы можете обрабатывать экземпляры только через эти * ссылки *. Эти ссылки могут передаваться по значению (без 'ref' или' out') или по ссылке (с 'ref' или' out'). – newacct

+0

Уточненный мой ответ. –

0

Передача значения по ссылке очень отличается от использования ключевого слова ref. Переводя это точке C или C++:

  • передавая объект, как передавая указатель
  • проходящего объект с ref, как передавая указатель на указатель.

Если вы хотите изменить значение своей переменной внутри функции, вам необходимо использовать ref или out.

+0

Передача по ссылке * точно * с использованием ключевого слова 'ref'. – newacct

1

Вы должны пометить параметр «out».

Для получения дополнительной информации о 'Out' смотреть на это:

https://msdn.microsoft.com/en-us/library/t3c3bfhx.aspx

+1

В описанном сценарии использование 'out' выгодно по сравнению с 'ref', поскольку оно дает более четкое сообщение о намерении вызова метода. Еще раз, самый точный ответ не получает галочку. –

 Смежные вопросы

  • Нет связанных вопросов^_^