3

I'm currently struggling to understand what it means when it's stated that with the 'out' keyword we're able to return multiple values. For example from the msdn site (https://msdn.microsoft.com/en-us/library/ee332485.aspx): "...The following examples uses out to return three variables with a single method call."

class OutReturnExample
{
    static void Method(out int i, out string s1, out string s2)
    {
        i = 44;
        s1 = "I've been returned";
        s2 = null;
    }
    static void Main()
    {
        int value;
        string str1, str2;
        Method(out value, out str1, out str2);
        // value is now 44
        // str1 is now "I've been returned"
        // str2 is (still) null;
    }
}

I'm not sure if i'm just not reading the description right but it seems that Method() doesn't actually return (doesn't use the 'return' keyword) anything at all and basically assigns the fields (similarly through passing by ref). This is consistent with other sources where they state that using 'out' can return multiple values. Am i misunderstanding the context of the return word or is it something along the lines that i'm not understanding the concept properly?

WonderfulWonder
  • 515
  • 1
  • 8
  • 20
  • 1
    The `out` keyword means that after the method call, those variables must have something assigned to. – dcg Apr 07 '17 at 12:25
  • 2
    It's semantically equivalent to return. You call a method and you have your "out" variables filled with results, just like when you call a method with return type and have one variable filled with result. – Evk Apr 07 '17 at 12:26
  • 1
    The `out` keyword, means that all those value in outer scope will be "created" and "assigned". You can say that they been returned, since `out` declares contract that those values has to be changed in current mehtod. – Tomasz Juszczak Apr 07 '17 at 12:27
  • 1
    You probably misunderstand the context of the return word =) It's not "_pass_ some value out" - it's "return execution _from_ the method". You first `void` method can be re-written as `static void Merhod(...) { ... ; s2 = null; return; }` Compiler allows you to omit the `return` at the end because it's obvious that you're returning from the method because there's nothing left to do. – Sergey.quixoticaxis.Ivanov Apr 07 '17 at 12:48

3 Answers3

7

The method indeed does not return a value as you noticed correctly. Both ref and out work with references.

ref will let the compiler know that the variable should already be initialized before it enters the function (this is useful when you used the variable before that function and want to change something now). out will let the compiler know that the object is initialized inside the function it's calling. So ref works both ways, out is out-only.

So, yes, it does not actually return something. But on the other hand, it will assign values to your variables through which your calling method also ends up with the new values. Essentially you can see this as a return.

So in short:

  • ref parameters - these have the same capabilities as C++ reference parameters, and

  • out parameters - these allow passing data back from a method, but not into the method.

I also suggest you read this SO answer and the corresponding blog of Jon Skeet about parameter passing. It will give you a lot of information about the concept. And as Jon Skeet notes, be careful when using ref and out:

It's basically a way of getting another return value, and should usually be avoided precisely because it means the method's probably trying to do too much.

Community
  • 1
  • 1
Jurjen
  • 1,376
  • 12
  • 19
4

You're right, the method can only return (in the sense that you are talking of) one thing at most. Or, as per your declaration (return type of void), when the method completes, it doesn't return anything at all to the calling code.

If you want to get multiple values back from your method, you have a couple of options:

  1. Return a class or struct — that is one thing, but it can contain multiple values (properties of that thing)

  2. Pass some parameters into the method with the out modifier, as per your example. out is similar to ref in that your method is dealing with the actual value and not a copy of it. But unlike with ref, the method has to assign values to any parameters marked as out before the method completes (you'll get a compiler error if it doesn't). You can have multiple parameters with an out modifier on them.

So it depends a bit on what you mean by return. In the sense of a return value, your example code returns nothing (it is declared with return type void), and if you changed it to have a return type it could at most return one thing as its return value. But in the sense of telling the calling code about what was done within the method, then with out parameters you can do that for multiple values.

Jinlye
  • 1,774
  • 18
  • 19
3

It is using the term return for its semantic meaning, rather than meaning its use as a keyword.

Semantically, when you use the out keyword, you are specifying two things:

  1. The parameter is NOT used for input.
  2. The parameter's value will be definitely assigned before the method returns.

In that respect, an out parameter is a value that is returned from the method.

The compiler does enforce these semantics. The following code will generate a couple of warnings:

public static void Test(out int x)
{
    Console.WriteLine(x);
}

Error CS0177 The out parameter 'x' must be assigned to before control leaves the current method

Error CS0269 Use of unassigned out parameter 'x'

Note that C#7 (aka Visual Studio 2017) will allow you to declare variables within the method call.

Given:

public static void  Test(out int x, out int y)
{
    x = 1;
    y = 2;
}

C# 7 lets you do this:

Test(out int x, out int y);
Console.WriteLine($"x = {x}, y = {y}");

This syntax makes it more obvious that something is being "returned", since the variables are being declared and initialised in the same statement.

Also in C# 7, you can use tuples instead of out, which I think is much nicer (and works a lot better with lambdas!).

The example above can be rewritten as follows in C#7:

public static (int x, int y)  Test()
{
    int x = 1;
    int y = 2;
    return (x, y);
}

Then you can do this:

(int x, int y) = Test();
Console.WriteLine($"x = {x}, y = {y}");
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276