Ссылочные типы C#
Попалась интересная задачка по C#, не могу понять, почему после функции Find(Checker Check1) значение Check1 = 11. Объясните подробно, пожалуйста.
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Calculate().ToString());
Console.ReadKey();
}
static void Find(Checker Check1)
{
Check1.Count += 10;
var Check2 = new Checker();
Check2.Count = Check1.Count;
Check2.Count += 100;
Check1 = Check2;
}
static void Find(ref Checker Check1)
{
Check1.Count += 1000;
var Check2 = new Checker();
Check2.Count = Check1.Count;
Check2.Count += 10000;
Check1 = Check2;
}
static void FindSimple(CheckerSimple Check1)
{
Check1.Count += 30;
CheckerSimple Check2;
Check2.Count = Check1.Count;
Check2.Count += 300;
Check1 = Check2;
}
static void FindSimple(ref CheckerSimple Check1)
{
Check1.Count += 300;
CheckerSimple Check2;
Check2.Count = Check1.Count;
Check2.Count += 3000;
Check1 = Check2;
}
static public int Calculate()
{
var Check1 = new Checker();
Check1.Count += 1;
Find(Check1);
Find(ref Check1);
CheckerSimple Check2;
Check2.Count = Check1.Count;
FindSimple(Check2);
FindSimple(ref Check2);
return Check2.Count;
}
}
class Checker
{
int count;
public int Count
{
get { return count; }
set { count = value; }
}
public Checker()
{
Count = 0;
}
}
struct CheckerSimple
{
public int Count;
}
Ответы (1 шт):
Функции хранят свои собственные параметры в своём стеке и поэтому надо понимать, что это разные переменные и ведут они себя соответственно. Когда вы вызываете Find, то переменные Main.Check1 и Find.Check1 указывают на одну область памяти.
Если вы перезаписали ссылку на объект в памяти в переменной Find.Check1, то она будет указывать на новый объект, а вот Main.Check1 на старый. Это суть ссылочных типов, когда меняются ссылки на объект в переменной. Поэтому ваш объект и хранит значение Heap.Check1 = 11. В то время как в Heap.Check2 будет ваше значение 1000.
Пометив параметр как ref вы грубо говоря связываете переменные, поэтому в остальных функциях из-за этого будут перезаписывать ссылки не только в Find.Check1, но и в Main.Check1.


