Это лучше всего иллюстрируется на примере:
public class C { public int P { get; set; } }
public class X
{
static void M(C c1, C c2, ref C c3, ref C c4)
{
c1.P = 11;
c2 = new C() { P = 12 };
c3.P = 13;
c4 = new C() { P = 14 };
}
static void Main()
{
C q1 = new C() { P = 1 };
C q2 = new C() { P = 2 };
C q3 = new C() { P = 3 };
C q4 = new C() { P = 4 };
M(q1, q2, ref q3, ref q4);
Console.WriteLine(q1.P);
Console.WriteLine(q2.P);
Console.WriteLine(q3.P);
Console.WriteLine(q4.P);
}
}
Что происходит?
q1 и c1 относятся к одному и тому же объекту, но имеют разные переменные. Мутирование c1.P мутирует q1.P, поскольку обе переменные относятся к одному и тому же объекту, поэтому q1 теперь 11.
q2 и c2 относятся к одному и тому же объекту, но представляют собой разные переменные. Мутирование c2 не мутирует q2, так как c2 и q2 - разные переменные; изменение одного не меняет другого. q2 остается 2, и новый объект потерян.
q3 и c3 - это два имени для одной и той же переменной и, следовательно, относятся к одному и тому же объекту. Когда вы меняете c3.P, который автоматически меняет q3.P, потому что это два имени для одной и той же вещи.
q4 и c4 - это два имени для одной и той же переменной, поэтому мутация q4 также мутирует c4.
Это имеет смысл?
К сожалению, ключевое слово для "make a alias to this variable" is "ref". Было бы более ясно, был ли это «псевдоним».
Чтобы ответить на второй вопрос: нет, это не делает цепочку ссылок. Давайте сделаем более четкий пример:
...
int c1 = 123;
M(ref c1);
...
void M1(ref int q1) { M2(ref q1); }
void M2(ref int q2) { M2(ref q2); }
Это говорит о том, что c1 и q1 разные названия одной и той же переменной, а q1 и q2 разные названия одной и той же переменной, и, следовательно, c1, q1 и q2 все псевдонимы друг для друга. В C# никогда не существует ссылки на ссылку на переменную, как в C++.
Также см. Например [Почему используется ключевое слово ref при передаче объекта?] (Http://stackoverflow.com/questions/186891/) и потоки в разделе «Связанные» столбца справа, при этом стр. –