В c# есть ссылка типы и значение типы. Типы значений передаются по значению, если вы не передаете их с ключевым словом ref
. Ссылочные типы всегда передаются по ссылке.
Например, если вы объявляете две переменные, подобные этой
List<int> myList = new List<int>();
int myint = 0;
myInt
содержит значение 0
, но myList
содержит только ссылку, которая указывает на фактический экземпляр List<int>
. Это означает, что когда вы передаете myInt
методу, вы просто передаете копию его значения. Когда вы передаете myList
, вы делаете то же самое - вы передаете копию его значения, но его значение является ссылкой на экземпляр List<int>
, поэтому копия этой ссылки по-прежнему ссылается на тот же List<int>
в куче.
Когда вы передаете переменную с ключевым словом ref
, вы фактически передаете указатель на исходную переменную. Если вы передадите myInt
с ключевым словом ref
, ваш метод получит указатель на myInt
, поэтому он сможет изменить его фактическое значение. Если вы передадите myList
с ключевым словом ref
, произойдет то же самое. Теперь ваш метод может изменить фактическое значение переменной myList
. Он может установить для него другую ссылку.
Вероятно, это легче понять, когда вы видите это на практике, поэтому здесь небольшое консольное приложение, показывающее разницу между двумя методами, которые отличаются только использованием ключевого слова ref
* 1033. *
static void Main(string[] args)
{
//create new instane of List<int> on the heap and store reference to it on the stack in 'myList 'variable
List<int> myList = new List<int>() { 1 };
//create new instance of int and store it on the stack in 'myInt' variable
int myint = 2;
//call MyMethod
//copy value of myInt (2) to the new stack frame and store it in 'i' variable
//copy value of myList (reference to List<int>) to the new stack frame and store it in 'list' variable
MyMethod(myint, myList);
Console.WriteLine(myint); //prints 2
Console.WriteLine(myList[0]); //prints 4
//call MyMethod
//inside new stack frame store pointer to 'myint' variable
//inside new stack frame store pointer to 'myList' variable
MyMethod(ref myint, ref myList);
Console.WriteLine(myint); //prints 3
Console.WriteLine(myList[0]); //prints 5
Console.ReadLine();
}
static void MyMethod(int i, List<int> list)
{
//store value of 3 on stack in variable 'i'
i = 3;
//use reference stored on stack in 'list' variable to find our instance of List<int> on the heap and store 4 under index 0
list[0] = 4;
//create new instane of List<int> on the heap and store reference to it on the stack, in 'list 'variable
list = new List<int>() { 5 };
}
static void MyMethod(ref int i, ref List<int> list)
{
//use pointer to 'myInt' variable to store value of 3 in 'myInt' variable
i = 3;
//use pointer to 'myList' variable to get reference stored in it and use that reference to find our instance of List<int> on the heap and store 4 under index 0
list[0] = 4;
//create new instane of List<int> on the heap and use pointer to 'myList' variable to store reference to that new instance inside 'myList' variable
list = new List<int>() { 5 };
}