Передача ссылки по ссылке

Как может быть полезно передать ссылочный объект по ссылке. Регулярное использование выглядит следующим образом:

public static void main()
{
    Student st = new Student();
    st.FirstName = "Marc";
    PutLastName(st);
    Console.WriteLLine(st.FirstName + " " + st.LastName);
}

public static PutLastName(Student student)
{
    student.LastName = "Anthony";
}

Зачем кому-то писать следующее, которое делает то же самое и печатает: «Марк Энтони»:

public static void main()
{
    Student st = new Student();
    st.FirstName = "Marc";
    PutLastName(ref st);
    Console.WriteLLine(st.FirstName + " " + st.LastName);
}

public static PutLastName(ref Student student)
{
    student.LastName = "Anthony";
}

person yazanpro    schedule 06.09.2013    source источник
comment
Это в основном обман: stackoverflow.com/questions/635915/. Вам следует просто прочитать документацию для ref, чтобы понять разницу: msdn.microsoft. com/en-us/library/14akc2c7.aspx. Конечно, я не думаю, что есть общие причины для использования ref, поэтому вашему мозгу может быть трудно принять существование такой вещи.   -  person rliu    schedule 06.09.2013


Ответы (4)


Это не то же самое .. под капотом.

Функционально он работает одинаково, да. Однако под капотом... сама ссылка передается при использовании ref. Без ref опорное значение копируется.

Думайте о ссылках как об указателях памяти. student имеет значение 1134.. адрес памяти. Когда вы не используете ref, 1134 применяется к новой ссылке... указывающей на тот же адрес памяти.

Использование ref может иметь опасные последствия, когда вы осознаете вышеизложенное. Например, рассмотрите это:

public static void PutLastName(Student student)
{
    student = new Student();
    student.LastName = "Whitehead";
}

// .. calling code ..
Student st = new Student();
st.FirstName = "Marc";
st.LastName = "Anthony";
PutLastName(st);
Console.WriteLLine(st.FirstName + " " + st.LastName); // "Marc Anthony"

Принимая во внимание, что использование ref:

public static void PutLastName(ref Student student)
{
    student = new Student();
    student.FirstName = "Simon";
    student.LastName = "Whitehead";
}

// .. calling code ..
Student st = new Student();
st.FirstName = "Marc";
st.LastName = "Anthony";
PutLastName(ref st);
Console.WriteLLine(st.FirstName + " " + st.LastName); // "Simon Whitehead"

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

person Simon Whitehead    schedule 06.09.2013
comment
Я прекрасно понял разницу, и вы попали в самую точку, когда сказали, что использование ref может быть опасным. Спасибо, - person yazanpro; 06.09.2013

Во второй версии ref означает, что PutLastName может изменить st.

person bazza    schedule 06.09.2013

Передача ссылки по ссылке позволяет вам не только редактировать данные, на которые ссылаются, но также позволяет изменять сам объект, на который он ссылается.

Разница в этих вариантах использования:

// from the Main's point of view, this function does absolutely nothing
public static PutLastName(Student student)
{
    student = new Student();
}

// This would clear Main's student.
public static PutLastName(ref Student student)
{
    student = new Student();
}

см. http://msdn.microsoft.com/en-us/library/14akc2c7.aspx

person Nicolas Louis Guillemot    schedule 06.09.2013

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

person newacct    schedule 06.09.2013