Параметры ВСЕГДА передаются по значению. Это означает, что в области активации создаётся копия ЗНАЧЕНИЯ параметра. При этом важно, ЧТО копируется в эту область. Для ссылочных типов возможны два варианта:
§ можно скопировать адрес объекта (ссылка как параметр),
§ можно скопировать адрес переменной, которая указывает на объект (ссылка на ссылку как параметр).
В первом случае параметр обеспечивает изменение полей объекта. Непосредственное изменение значения этой ссылки (возможно в результате создания новых объектов и присвоения значения новой ссылки параметру) означает лишь изменение значения параметра, который в данном случае играет роль обычной переменной, сохраняющей значение какого-то адреса (адреса ранее объявленного объекта).
Во втором случае параметр сохраняет адрес переменной, объявленной в теле вызывающего метода. При этом в вызываемом методе появляется возможность как изменения значений полей объекта, так и непосредственного изменения значения переменной.
Следующий программный код демонстрирует специфику передачи параметров.
using System;
namespace Ref_RefRef
{
/// <summary>
/// Ссылка и ссылка на ссылку.
/// </summary>
class WorkClass
{
public int x;
public WorkClass()
{
x = 0;
}
public WorkClass(int key)
{
x = key;
}
public WorkClass(WorkClass wKey)
{
x = wKey.x;
}
}
class ClassRef
{
static void Main(string[] args)
{
WorkClass w0 = new WorkClass();
Console.WriteLine(“on start: {0}”, w0.x); //_: 0
f0(w0);
Console.WriteLine(“after f0: {0}”, w0.x); //0: 1
f1(w0);
Console.WriteLine(“after f1: {0}”, w0.x); //1: 1
f2(ref w0);
Console.WriteLine(“after f2: {0}”, w0.x); //2: 10
f3(ref w0);
Console.WriteLine(“after f3: {0}”, w0.x); //3: 3
// Ещё один объект...
WorkClass w1 = new WorkClass(w0);
ff(w0, ref w1);
if (w0 == null) Console.WriteLine(“w0 == null”);
else Console.WriteLine(“w0 != null”); // !!!
if (w1 == null) Console.WriteLine(“w1 == null”); // !!!