Правильный способ думать об этом: используйте ref / out, когда вы хотите создать псевдоним для переменной . То есть когда вы говорите:
void M(ref int x) { x = 10; }
...
int q = 123;
M(ref q);
что вы говорите: "x - это другое имя переменной q" . Любые изменения в содержимом x изменяют q, а любые изменения в содержимом q изменяют x, потому что x и q - это просто два имени для точно такого же места хранения .
Обратите внимание, что это полностью отличается от двух переменных, относящихся к одному и тому же объекту:
object y = "hello";
object z = y;
Здесь у нас есть две переменные , каждая переменная имеет одно имя , каждая переменная относится к один объект , и обе переменные относятся к тот же объект . В предыдущем примере у нас есть только одна переменная с двумя именами .
Это ясно?