In C #, when sending a parameter to a method, when should we use "ref" and "out" and when without them?

In C #, when sending a parameter to a method, when should we use "ref" and "out" and when without them?

+4
source share
7 answers

In general, you should avoid using ref and out if possible.

Use ref if you want the method to change the value. Use when a method should always assign a value.

The difference between ref and out is that when using out, the compiler enforces the rule that you need to assign something to the out parameter before returning. When using ref, you must assign a value to the variable before use as the ref parameter.

Obviously, this is higher when you write your own methods. If you need to call methods that were declared using the ref or out modifiers according to their parameters, you must use the same modifier in front of your parameter when calling the method.

Also remember that C # passes reference types (classes) by reference (as in, a reference is passed by value). Therefore, if you provide some method of reference type as a parameter, the method can modify the data of the object; even without ref or out. But it cannot change the link itself (for example, it cannot change which object is referenced).

+13
source

They are mainly used to get multiple return values ​​from a method call. Personally, I tend not to use them. If I want to get some return values ​​from a method, I will create a small class to store them.

ref and out are used when you want to return something from a method in this parameter. As far as I remember, they both actually come down to the same IL, but C # adds some additional things, so you have to be specific.

Here are some examples:

static void Main(string[] args) { string myString; MyMethod0(myString); Console.WriteLine(myString); Console.ReadLine(); } public static void MyMethod0(string param1) { param1 = "Hello"; } 

The above will not compile because myString is never initialized. If myString is initialized to string.Empty, then the output of the program will be an empty string, because all MyMethod0 this assigns a new line to the local link to param1.

 static void Main(string[] args) { string myString; MyMethod1(out myString); Console.WriteLine(myString); Console.ReadLine(); } public static void MyMethod1(out string param1) { param1 = "Hello"; } 

myString is not initialized in the Main method, but the program displays "Hello". This is because the link myString in the Main method is updated with MyMethod1. MyMethod1 does not expect param1 to already contain anything, so it can be left uninitialized. However, the method must assign something.

 static void Main(string[] args) { string myString; MyMethod2(ref myString); Console.WriteLine(myString); Console.ReadLine(); } public static void MyMethod2(ref string param1) { param1 = "Hello"; } 

This, again, will not compile. This is because ref requires myString in the Main method to be initialized first with something. But, if the Main method is changed so that myString is initialized to string.Empty, then the code will compile, and the output will be Hello.

Thus, the difference cannot be used with an uninitialized object; ref must be passed to the initialized object. And if you pass an object without reference to it, it cannot be replaced.

Just to be clear: if the passed object is already a reference type, then the method can update the object, and the updates are reflected in the calling code, however, the reference to the object cannot be changed. Therefore, if I write the code as follows:

 static void Main(string[] args) { string myString = "Hello"; MyMethod0(myString); Console.WriteLine(myString); Console.ReadLine(); } public static void MyMethod0(string param1) { param1 = "World"; } 

Exiting the program will be Hello, not World, because the method only changed its local copy of the link, not the link that was passed.

Hope this makes sense. My general rule is simply not to use them. I feel this is a return to the days before the TOE. (But, this is just my opinion)

+12
source

(this is an addition to existing answers - a few additional considerations)

There is another use case for ref with C #, which is more common in things like XNA ... Usually, when you pass a value type ( struct ), it is cloned. This uses stack space and several processor cycles and has the side effect that any changes to the struct in the called method are lost.

(aside: usually a struct should be immutable, but mutable structures are not uncommon in XNA)

To get around this, quite often you can see ref in such programs.

But in most programs (i.e. where you use class es as the default), you can usually just pass the link "by value" (i.e. no ref / out ).


Another very example of using out is the Try* pattern, for example:

 string s = Console.ReadLine(); int i; if(int.TryParse(s, out i)) { Console.WriteLine("You entered a valid int: " + i); } 

Or similarly TryGetValue in the dictionary.

Instead, you can use a tuple, but this is such a general pattern that he intelligently understands even by people who work too hard ref / out .

+6
source

Very simple. You are using the exact same keyword that the parameter was originally declared in the method. If it was declared as out , you should use out . If it was declared as ref , you should use ref .

+2
source

In addition to Colin's detailed answer, you can also use parameters to return multiple values ​​from a single method call. See, for example, the method below, which returns 3 values.

 static void AssignSomeValues(out int first, out bool second, out string third) { first = 12 + 12; second = false; third = "Output parameters are okay"; } 

You can use it like this:

 static void Main(string[] args) { int i; string s; bool b; AssignSomeValues(out i, out b, out s); Console.WriteLine("Int value: {0}", i); Console.WriteLine("Bool value: {0}", b); Console.WriteLine("String value: {0}", s); //wait for enter key to terminate program Console.ReadLine(); } 

Just make sure that you assign a valid value to each out parameter to avoid getting an error.

+2
source

Try to avoid using ref. Out is good because you know what will happen, the old value will disappear, and the new value will be in your variable, even if the function failed. However, just by looking at the function, you have no idea what will happen to the ref parameter. It can be the same, modified or completely new object.

Whenever I see a ref, I'm nervous.

0
source

ref should be avoided (I believe that the fx-cop rule also exists for this), however, use ref when the object that is the link itself can change. If you see the keyword "ref", then you know that the base object can no longer refer to the same variable after calling the method.

0
source

All Articles