C# Ref Out

  • The ref modifier is used to make an argument passing by reference instead by value.
  • Any changes in a ref parameter will reflect to the argument of the calling method.
  • The ref keyword must be used in both the method definition and the calling method. Otherwise, a compile time error will be issued.
  • In the calling method, the ref argument must be initialized before it is passed to the ref parameter of the defined method.

Example 01-60-01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;

public class RefInValueType
{
    public static void Main()
    {
        int i = 1;

        testNoRef(i);
        Console.WriteLine("i = {0}", i);

        testRef(ref i);
        Console.WriteLine("i = {0}", i);
        Console.Read();
    }

    public static void testNoRef(int i)
    {
        i++;
    }

    public static void testRef(ref int i)
    {
        i++;
    }
}

Output

i = 1
i = 2

Explanation

  • Line 3-26: Defined a class with 3 static methods.
  • Line 17-20: Defined a static method testNoRef(int i). A static method is a class level method instead of an instance method. C# static will be introduced later.
  • Line 22-25: Defined a static method testRef(ref int i). The ref modifier indicate the parameter is transferred by reference.
  • Line 5: The program starts at Main method.
  • Line 7: Define a local integer i = 1.
  • Line 9: Call the static method testNoRef(i). The value of the argument will be transferred to the method. In line 19, i is a local integer variable in the method testNoRef and will be destroyed after the method finishes running and returns to the caller.
  • Line 10: The local variable i defined in the line 7 of Main method will not be changed after calling testNoRef method because the argument was passed by value. So this line will output i = 1.
  • Line 12: Call the static method testRef(ref i). This time i will be passed by reference. This means i in the method both Main and testRef has the same reference which point to the same memory location. so after i increments by 1 in line 24, i equals to 2 and it makes the value of i in the Main method changed to 2 as well.
  • Line 13: Output i = 2.

Example 01-60-02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;

public class A
{
    public int i;
}

public class TestRef
{
    public static void Main()
    {
        A a = new A();
        a.i = 1;
        Console.WriteLine("i={0}",a.i);

        testNoRef(a);
        Console.WriteLine("i={0}", a.i);

        testRef(ref a);
        Console.WriteLine("i={0}", a.i);

        Console.Read();
    }

    public static void testNoRef(A aa)
    {
        aa = new A();
        aa.i = 2;
    }

    public static void testRef(ref A aa)
    {
        aa = new A();
        aa.i = 3;
    }
}

Output

i=1
i=1
i=3

Explanation

  • Line 3-6: Define a public class A with the only public field i.
  • Line 8-36: Define a test class with 3 static methods.
  • Line 12-14: Instantiate class A, assign 1 to the field i and output.
  • Line 16: Call a static method testNoRef which was defined in line 25-29.
  • Line 25: The parameter is a local reference of class A without ref putting ahead.
  • Line 27: aa points to a new reference of A.
  • Line 28: Set the value of the field i of the new reference.
  • Line 29: The method testNoRef is over and the resource aa will be released and aa will not be copied back to the calling method.
  • Line 17: Output i=1 because a.i has never been changed.
  • Line 19: Call a static method testRef which was defined in line 31-35.
  • Line 31: A ref parameter was defined here.
  • Line 33-34: It is nearly the same as that in line 27-28.
  • Line 35: The method testRef is over and the value of aa will be copied back to a in line 19 because of ref parameter. a holds a reference of A and the value a.i was changed in line 34.
  • Line 20: Output i=3.

What would be happened if line 17 were commented out?

The output in line 17 would be i=2 instead of i=1 because aa or a is a reference type.

  • We'll discuss the keyword out as a parameter modifier in this section.
  • Like ref, out is also used to pass arguments by reference and must be used in both method definition and the calling method explicitly.
  • The out keyword can be used on an uninitialized variable but ref is only used to an initialized variable.
  • The out variable must be assigned in the called method otherwise you will get a compile time error.

Example 01-60-03

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;

public class A
{
    public int i;
}

public class TestOut
{
    public static void Main()
    {
        int j;
        test1(out j);
        Console.WriteLine("j={0}", j);

        A a;
        test2(out a);
        Console.WriteLine("i={0}", a.i);

        Console.Read();
    }

    public static void test1(out int i)
    {
        i = 8;
    }

    public static void test2(out A aa)
    {
        aa = new A();
        aa.i = 6;
    }
}

Output

j=8
i=6

Explanation

  • Line 3-6: Define a public class A with the only public field i.
  • Line 8-33: Define a test class with 3 static methods.
  • Line 12: Define an integer variable without initialized.
  • Line 13: Call a static method test1 and j is passed as an out argument.
  • Line 25: In the method, the out parameter i is assigned with 8 and passed back to j.
  • Line 14: Output j=8.
  • Line 16: Define an A type variable.
  • Line 17: Call test2 method. The variable a is passed as an out argument.
  • Line 30-31: Create an instance of A, assign it to aa and assign 6 to aa.i. At the end of the method, aa is passed to a because of out modifier.
  • Line 18: Output i=6 which was assigned in line 31.

What will be happened if the assignment statement is removed?

You will get a compile time error because the out parameter i must be assigned before the method is over running.