В документации microsoft написано, что если передавать ссылочный тип по значению, то фактически в метод передаётся копия на ссылку. Тогда почему если в методе изменить этот параметр, то потом вернувшись в main значение остаётся изменённым? Если бы передавалась сама ссылка а не её копия тогда было бы понятно.
Можно рассмотреть такой пример
class MyClass
{
// инициализируем поле 20.
public int Val = 20;
}
class Program
{
static void MyMethod(MyClass f1, int f2)
{
// Увеличиваем на 5 значение поля у ссылочного типа
f1.Val = f1.Val + 5;
// Увеличиваем на 5 значение у значимого типа
f2 = f2 + 5;
Console.WriteLine($"Окончание метода MyMethod(): f1.Val=={f1.Val}, f2=={f2}");
}
static void Main(string[] args)
{
//создаем ссылочный тип
MyClass a1 = new MyClass();
//создаем значимый тип
int a2 = 10;
Console.WriteLine($"До вызова метода MyMethod(): a1.Val=={a1.Val}, a2=={a2}");
//вызоваем метод
MyMethod(a1, a2);
Console.WriteLine($"После отработки метода MyMethod(): a1.Val=={a1.Val}, a2=={a2}");
Console.ReadLine();
}
}
Результат работы такой
Что происходит при этом в Стеке
и Куче
поможет понять такая иллюстрация
Пример и иллюстрация взяты из книги Illustrated C# 7
P.S. для случая передачи параметров по ссылке изменим в предыдущем примере метод так
static void MyMethod(ref MyClass f1, ref int f2)
и его вызов так
MyMethod(ref a1, ref a2);
Вывод будет таким Иллюстрация к происходящему
Теперь изменим пример так
class Program
{
static void MyMethod(MyClass f1)
{
f1.Val = 50;
Console.WriteLine($"После изменения значения в MyMethod(): { f1.Val }");
//здесь мы изменяем ссылку на др. экземпляр класса
f1 = new MyClass();
Console.WriteLine($"После присвоения нового экземпляра класса в MyMethod(): {f1.Val}");
}
static void Main(string[] args)
{
MyClass a1 = new MyClass();
Console.WriteLine($"До вызова метода MyMethod():{a1.Val}");
MyMethod(a1);
Console.WriteLine($"После отработки метода MyMethod(): {a1.Val}");
Console.ReadLine();
}
}
Результат работы такой Иллюстрация происходящего
Теперь снова изменим метод
static void MyMethod(ref MyClass f1)
и его вызов
MyMethod(ref a1);
Результат работы такой Иллюстрация к присходящему Тут уж все возможные случаи продемонстрированы.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Как работать с sfml на с# в линуксЕсть идея с моно, но есть желание разрабатывать сразу на ubuntu и запускать
Помогите разобраться с правильным использованием многопоточности в виндовс-службе, написанной наnet core
На выходе в отладчике dTest3 036000000000001364
Можно ли как-то сделать так, что бы не вызывался Dispose при использовании оберток StreamReader / StreamWriter?