Why must use “out” instead of ref?

2019-06-24 16:40发布

问题:

i wrote some code blocks about ref -out declaration. i think that ref is most useful out. Ok. why i need to use out. i can use always ref everytime:

namespace out_ref
{
    class Program
    {
        static void Main(string[] args)
        {
            sinifA sinif = new sinifA();
            int test = 100;
            sinif.MethodA(out test);
            Console.WriteLine(test.ToString());

            sinif.MethodB(ref test);
            Console.WriteLine(test.ToString());
            Console.ReadKey();
        }
    }

    class sinifA
    {

        public void MethodA(out int a)
        {
            a = 200;
        }

        int _b;
        public void MethodB(ref int b)
        {
            _b = b;
            b = 2*b;
        }
    }

}

回答1:

Yes you can use ref every time but they have different purposes. ref is used for when a parameter is both an input and an output. out is used when the parameter is an output only. It can be used to pass an input but it makes it so the user of a function does not need to declare an instance before using the function because you are in effect saying that you will guarantee an instance is created. It is especially useful in the TryXXX pattern when you are getting a value from a collection



回答2:

When you have a parameter with out attached to it, you don't need to initialize it, before you pass it on to the method that accepts it.

The out keyword causes arguments to be passed by reference. 
This is like the ref keyword, except that ref requires that the variable be initialized 
before it is passed.

From: http://msdn.microsoft.com/en-us/library/ee332485.aspx



回答3:

An out parameter is guaranteed to be initialized during the function. This provides a more strict contract to your caller. It also allows you to write code like this:

int i;
MyFunc(out i);
.. < use i > ..

without getting a compiler error for an uninitialized variable.



回答4:

ref and out is handled the same way internally, they're both passing a variable by reference.

The difference is in the initialization semantics, who is responsible for ensuring the variable has a valid start value, and it is enforced by the compiler.

With out parameters, it's the method you call. Whatever value is in the variable you pass by reference before you call the method is irrelevant. The compiler will complain if the method you call has an execution path that fails to set a new value for its parameter. This means that whatever value is in the variable before you call the method is guaranteed to be overwritten, even if it is with the same value.

With ref parameters, it's the method that calls. The value of the variable will be passed to the method being called, which can then inspect its parameter and optionally change it. The compiler will complain the method that calls does not initialize the variable with a value before making the call.

So basically, it's all down to what the compiler will complain about. Is it the calling code that must ensure there is a value in the variable or is it the called code.



回答5:

Out Parameters

In addition to passing values by reference, you can also specify that a given parameter is an out parameter by using the out keyword, which is used in the same way as the ref keyword (as a modifier to the parameter in the function definition and in the function call). In effect, this gives you almost exactly the same behavior as a reference parameter in that the value of the parameter at the end of the function execution is returned to the variable used in the function call. However, there are important differences:

  1. Whereas it is illegal to use an unassigned variable as a ref parameter, you can use an unassigned variable as an out parameter
  2. An out parameter must be treated as an unassigned value by the function that uses it.

This means that while it is permissible in calling code to use an assigned variable as an out parameter, the value stored in this variable is lost when the function executes.

As an example, consider an extension to the MaxValue() function shown earlier, which returns the maximum value of an array. Modify the function slightly so that you obtain the index of the element with the maximum value within the array. To keep things simple, obtain just the index of the first occurrence of this value when there are multiple elements with the maximum value. To do this, you add an out parameter by modifying the function as follows:

static int MaxValue(int[] intArray, out int maxIndex)

{ int maxVal = intArray[0]; maxIndex = 0; for (int i = 1; i < intArray.Length; i++) { if (intArray[i] > maxVal) { maxVal = intArray[i]; maxIndex = i; } } return maxVal; }

You might use this function as shown here:

int[] myArray = {1, 8, 3, 6, 2, 5, 9, 3, 0, 2};

int maxIndex; Console.WriteLine(“The maximum value in myArray is {0}”, MaxValue(myArray, out maxIndex)); Console.WriteLine(“The first occurrence of this value is at element {0}”, maxIndex + 1);

This results in the following:

The maximum value in myArray is 9

The first occurrence of this value is at element 7

One has been added to the value of maxIndex returned here when it is displayed onscreen. This is to translate the index to a more readable form, so that the first element in the array is referred to as element 1, rather than element 0.