In C#, most methods can have zero or more parameters, which define the data that must be provided to the method. Any code that calls a method must pass data (called parameters) to the method. A method declares its inputs as parameters, and they are provided as parameters by the calling code.
For example, consider the following method and subsequent method calls.
static void Greet(string greeting){ Console.WriteLine(greeting); } ... Greet("Hello");
In the above example, greeting is the parameter of the Greet() method, and "Hello" is the parameter passed to the method.
When you call a method and pass arguments, they are passed by value, which means a copy of the value is created when passed to the method. Any changes made to the parameters inside the method are not reflected on the original variables.
using System; int number = 8; Increase(number); Console.WriteLine(number); // prints 8 static void Increase(int num){ num = num + 1; Console.WriteLine(num); // prints 9 }
When you pass a reference type variable (such as an object), C# still copies the reference by value because the variable holds the reference, not the actual object. So even if you pass a copy of the reference variable, they all refer to the same object in memory. Therefore, any changes made to the object by variables inside the method are visible to variables outside the method.
using System; var john = new User{ Name = "John", Salary = 50000 }; Promote(john); Console.WriteLine(john.Salary); // prints 60000 static void Promote(User u){ u.Salary += 10000; Console.WriteLine(u.Salary); // prints 60000 }
However, if you change the value of the variable itself inside the method, the change will not be reflected outside the method because only the copy is changed, not the actual object. For example, we can assign a parameter to null inside a method and the actual variable will remain unchanged.
using System; var john = new User{ Name = "John", Salary = 50000 }; Promote(john); Console.WriteLine(john.Salary); // prints 50000 static void Promote(User u){ u = null; }
C# allows the use of three different modifier keywords to control the parameters of a method.
C# allows you to pass parameters by reference using the ref modifier. It doesn't matter whether the variable being passed is a reference type or a value type. argument and argument will reference the same memory location.
In the following example, setting parameter u to null will also make the john variable null, thus throwing a null reference exception.
Example
using System; var john = new User{ Name = "John", Salary = 50000 }; Promote(ref john); Console.WriteLine(john.Salary); // throws System.NullReferenceException static void Promote(ref User u){ u = null; }
Parameters passed using the ref modifier must be initialized before passing.
It is similar to the ref modifier, except:
The parameters do not need to be initialized before entering the function
Parameters must be initialized (assigned) before coming out of the function
In the example below, the Hire function initializes the one passed to it via the out modifier new user object. Note that the variable john is declared on the fly when the Hire method is called.
using System; Hire(out User john); Console.WriteLine(john.Salary); // prints 50000 static void Hire(out User u){ u = new User{ Name = "John", Salary = 50000 }; }
Like the ref modifier, variables marked by the out modifier are passed by reference.
Usually out > Variable is used to get multiple return values from a function as follows -
using System; var john = new User{ Name = "John", Salary = 50000 }; bool shouldPromote = Raise(john.Salary, out double hike); Console.WriteLine(shouldPromote); // True Console.WriteLine($"Hike Amount = {hike}"); // prints 5000 static bool Raise(int salary, out double hike){ hike = salary * 0.1; return hike < 7000; }
It is similar to ref and out parameters, but the difference is that the method that accepts the in parameter cannot modify the value of the parameter. If modification is attempted, the C# compiler will generate a compile-time error.
inParameters can avoid copying memory of large value types into parameter variables and prevent objects from being accidentally modified. This is useful when passing large value types to methods.
var point = new Coord(); Verify(point); static void Verify(in Coord c){ // error: Cannot assign to variable 'in Coord' because it is a readonly variable c = new Coord(); } struct Coord{ public int X; public int Y; }
Real-time demonstration
using System; class Program{ static void Main(){ int number = 8; Increase(number); Console.WriteLine(number); // prints 8 var john = new User { Name = "John", Salary = 50000 }; Promote(john); Console.WriteLine(john.Salary); // prints 60000 Leave(john); Console.WriteLine(john.Salary); // prints 60000 LeaveByRef(ref john); Console.WriteLine(john?.Salary); // prints nothing User dave; Hire(out dave); Console.WriteLine(dave.Salary); // prints 50000 } static void Increase(int num){ num = num + 1; Console.WriteLine(num); // prints 9 } static void Promote(User u){ u.Salary += 10000; Console.WriteLine(u.Salary); // prints 60000 } static void Leave(User u){ u = null; } static void LeaveByRef(ref User u){ u = null; } static void Hire(out User u){ u = new User{ Name = "John", Salary = 50000 }; } } class User{ public string Name { get; set; } public int Salary { get; set; } }
9 8 60000 60000 60000 50000
The above is the detailed content of What is the usage of ref, out and in keywords in C#?. For more information, please follow other related articles on the PHP Chinese website!