The document discusses passing parameters by reference vs by value in C#, and the differences between the ref and out keywords. It provides code examples demonstrating how:
- Parameters passed by reference (using ref) allow the parameter value to be modified within the method and have those changes persist outside the method.
- Parameters passed with out must be assigned a value before the method returns, while parameters passed with ref can be assigned or left unchanged.
- When passing a reference type (like a List) by value, it passes the reference by value, so changes within the method are reflected outside.
- The ref and out keywords are used to pass value types (like int) by reference, with out ensuring the
The document discusses passing parameters by reference vs by value in C#, and the differences between the ref and out keywords. It provides code examples demonstrating how:
- Parameters passed by reference (using ref) allow the parameter value to be modified within the method and have those changes persist outside the method.
- Parameters passed with out must be assigned a value before the method returns, while parameters passed with ref can be assigned or left unchanged.
- When passing a reference type (like a List) by value, it passes the reference by value, so changes within the method are reflected outside.
- The ref and out keywords are used to pass value types (like int) by reference, with out ensuring the
The document discusses passing parameters by reference vs by value in C#, and the differences between the ref and out keywords. It provides code examples demonstrating how:
- Parameters passed by reference (using ref) allow the parameter value to be modified within the method and have those changes persist outside the method.
- Parameters passed with out must be assigned a value before the method returns, while parameters passed with ref can be assigned or left unchanged.
- When passing a reference type (like a List) by value, it passes the reference by value, so changes within the method are reflected outside.
- The ref and out keywords are used to pass value types (like int) by reference, with out ensuring the
Section 31.1: Passing by reference using ref keyword
From the documentation : In C#, arguments can be passed to parameters either by value or by reference. Passing by reference enables function members, methods, properties, indexers, operators, and constructors to change the value of the parameters and have that change persist in the calling environment. To pass a parameter by reference, use the ref or out keyword. The difference between ref and out is that out means that the passed parameter has to be assigned before the function ends.in contrast parameters passed with ref can be changed or left unchanged. using System; class Program { static void Main(string[] args) { int a = 20; Console.WriteLine("Inside Main - Before Callee: a = {0}", a); Callee(a); Console.WriteLine("Inside Main - After Callee: a = {0}", a); Console.WriteLine("Inside Main - Before CalleeRef: a = {0}", a); CalleeRef(ref a); Console.WriteLine("Inside Main - After CalleeRef: a = {0}", a); Console.WriteLine("Inside Main - Before CalleeOut: a = {0}", a); CalleeOut(out a); Console.WriteLine("Inside Main - After CalleeOut: a = {0}", a); Console.ReadLine(); } static void Callee(int a) { a = 5; Console.WriteLine("Inside Callee a : {0}", a); } static void CalleeRef(ref int a) { a = 6; Console.WriteLine("Inside CalleeRef a : {0}", a); } static void CalleeOut(out int a) { a = 7; Console.WriteLine("Inside CalleeOut a : {0}", a); } } Output : GoalKicker.com – C# Notes for Professionals 130 Inside Main - Before Callee: a = 20 Inside Callee a : 5 Inside Main - After Callee: a = 20 Inside Main - Before CalleeRef: a = 20 Inside CalleeRef a : 6 Inside Main - After CalleeRef: a = 6 Inside Main - Before CalleeOut: a = 6 Inside CalleeOut a : 7 Inside Main - After CalleeOut: a = 7 Section 31.2: Changing values elsewhere public static void Main(string[] args) { var studentList = new List<Student>(); studentList.Add(new Student("Scott", "Nuke")); studentList.Add(new Student("Vincent", "King")); studentList.Add(new Student("Craig", "Bertt")); // make a separate list to print out later var printingList = studentList; // this is a new list object, but holding the same student objects inside it // oops, we've noticed typos in the names, so we fix those studentList[0].LastName = "Duke"; studentList[1].LastName = "Kong"; studentList[2].LastName = "Brett"; // okay, we now print the list PrintPrintingList(printingList); } private static void PrintPrintingList(List<Student> students) { foreach (Student student in students) { Console.WriteLine(string.Format("{0} {1}", student.FirstName, student.LastName)); } } You'll notice that even though the printingList list was made before the corrections to student names after the typos, the PrintPrintingList method still prints out the corrected names: Scott Duke Vincent Kong Craig Brett This is because both lists hold a list of references to the same students. SO changing the underlying student object propogates to usages by either list. Here's what the student class would look like. public class Student { public string FirstName { get; set; } public string LastName { get; set; } public Student(string firstName, string lastName) { GoalKicker.com – C# Notes for Professionals 131 this.FirstName = firstName; this.LastName = lastName; } }
Section 31.3: ref vs out parameters
Code class Program { static void Main(string[] args) { int a = 20; Console.WriteLine("Inside Main - Before Callee: a = {0}", a); Callee(a); Console.WriteLine("Inside Main - After Callee: a = {0}", a); Console.WriteLine(); Console.WriteLine("Inside Main - Before CalleeRef: a = {0}", a); CalleeRef(ref a); Console.WriteLine("Inside Main - After CalleeRef: a = {0}", a); Console.WriteLine(); Console.WriteLine("Inside Main - Before CalleeOut: a = {0}", a); CalleeOut(out a); Console.WriteLine("Inside Main - After CalleeOut: a = {0}", a); Console.ReadLine(); } static void Callee(int a) { a += 5; Console.WriteLine("Inside Callee a : {0}", a); } static void CalleeRef(ref int a) { a += 10; Console.WriteLine("Inside CalleeRef a : {0}", a); } static void CalleeOut(out int a) { // can't use a+=15 since for this method 'a' is not intialized only declared in the method declaration a = 25; //has to be initialized Console.WriteLine("Inside CalleeOut a : {0}", a); } } Output Inside Main - Before Callee: a = 20 Inside Callee a : 25 Inside Main - After Callee: a = 20 Inside Main - Before CalleeRef: a = 20 Inside CalleeRef a : 30 Inside Main - After CalleeRef: a = 30 GoalKicker.com – C# Notes for Professionals 132 Inside Main - Before CalleeOut: a = 30 Inside CalleeOut a : 25 Inside Main - After CalleeOut: a = 25
Section 31.4: Assignment
var a = new List<int>(); var b = a; a.Add(5); Console.WriteLine(a.Count); // prints 1 Console.WriteLine(b.Count); // prints 1 as well Assigning to a variable of a List<int> does not create a copy of the List<int>. Instead, it copies the reference to the List<int>. We call types that behave this way reference types. Section 31.5: Dierence with method parameters ref and out There are two possible ways to pass a value type by reference: ref and out. The difference is that by passing it with ref the value must be initialized but not when passing it with out. Using out ensures that the variable has a value after the method call: public void ByRef(ref int value) { Console.WriteLine(nameof(ByRef) + value); value += 4; Console.WriteLine(nameof(ByRef) + value); } public void ByOut(out int value) { value += 4 // CS0269: Use of unassigned out parameter `value' Console.WriteLine(nameof(ByOut) + value); // CS0269: Use of unassigned out parameter `value' value = 4; Console.WriteLine(nameof(ByOut) + value); } public void TestOut() { int outValue1; ByOut(out outValue1); // prints 4 int outValue2 = 10; // does not make any sense for out ByOut(out outValue2); // prints 4 } public void TestRef() { int refValue1; ByRef(ref refValue1); // S0165 Use of unassigned local variable 'refValue' int refValue2 = 0; ByRef(ref refValue2); // prints 0 and 4 int refValue3 = 10; ByRef(ref refValue3); // prints 10 and 14 } The catch is that by using out the parameter must be initialized before leaving the method, therefore the following GoalKicker.com – C# Notes for Professionals 133 method is possible with ref but not with out: public void EmtyRef(bool condition, ref int value) { if (condition) { value += 10; } } public void EmtyOut(bool condition, out int value) { if (condition) { value = 10; } } //CS0177: The out parameter 'value' must be assigned before control leaves the current method This is because if condition does not hold, value goes unassigned. Section 31.6: Passing by reference If you want the Value Types vs Reference Types in methods example to work properly, use the ref keyword in your method signature for the parameter you want to pass by reference, as well as when you call the method. public static void Main(string[] args) { ... DoubleNumber(ref number); // calling code Console.WriteLine(number); // outputs 8 ... } public void DoubleNumber(ref int number) { number += number; } Making these changes would make the number update as expected, meaning the console output for number would be 8.