0

My question really just centers around one thing, mainly. What does the out keyword do, in this example branch, exactly?

if (!OAuthWebSecurity.TryDeserializeProviderUserId(loginData, out provider, out providerUserId)) {
            Response.Redirect("~/Account/Manage");
            return;
        }

I have looked here: http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.80).aspx

But the truth is, I don't know what an "argument passed by reference" means anymore than I know what the "ref" keyword is/does.

Sorry so new to this aspect, but I just can't seem to wrap my head around what this does.

This snippet is from the RegisterService.cshtml file in WebMatrix2's "Starter Site" template.

Jason Watkins
  • 3,766
  • 1
  • 25
  • 39
VoidKing
  • 6,282
  • 9
  • 49
  • 81
  • I realize that this question is really close to a couple of other questions asked on SO, but I feel like both of the OPs in those questions understood a bit more than I did about it, and I couldn't really grasp the nature of 'why' anyone would use out/ref – VoidKing Apr 01 '13 at 21:46
  • 1
    You might want to read [Parameter passing in C#](http://www.yoda.arachsys.com/csharp/parameters.html) by Jon Skeet – Conrad Frix Apr 01 '13 at 22:09

2 Answers2

3

It means that those parameters are the output of the procedure. It's one way to "return" multiple values from a procedure without creating a class to store the results. In this case there are three "results" (the two parameters plus the true Boolean return value).

If C# allowed multiple return values it would be the equivalent of:

bool canDeserialize;
canDeserialize, provider, providerUserId = OAuthWebSecurity.TryDeserializeProviderUserId(loginData); 
if (!canDeserialize){
            Response.Redirect("~/Account/Manage");
            return;
        }

Another option that is valid in C# is to create a class to store the results:

public class ProviderParseResults
{
   public string Provider {get; set;}
   public string ProviderUserId {get; set;}
}

and then use it this way:

ProviderParseResults results = OAuthWebSecurity.TryDeserializeProviderUserId(loginData); 
if (results == null){
            Response.Redirect("~/Account/Manage");
            return;
        }

string provider = results.Provider;
string providerUserId = results.ProviderUserId;
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • In addition, the `out` keyword specifies that the variable **must be assigned** before leaving the method body. Whereas, `ref` does not force this requirement. – Simon Whitehead Apr 01 '13 at 21:37
  • Output of what procedure? The method call itself? So instead of passing in variables you are taking them out after the method is executed? I don't think I'm getting it quite right am I? – VoidKing Apr 01 '13 at 21:38
  • Technically, you can still pass the `out` values into the method itself; out only requires that the method assigns a value to them. Also, `ref` may return values just as easily, the difference being it doesn't require them being assigned in the method. – Brad M Apr 01 '13 at 21:38
  • 1
    @VoidKing Think of the `out` parameters as a return value from a method. Using `out` is saying "Okay, here are some variables. **You must store something in them when I call you Mr. Method**. – Simon Whitehead Apr 01 '13 at 21:41
  • Okay, so after this method is called with its 2 out variables (can I call them that?), I can manipulate these variables, like I could any other variable passed into a method, only the method will return the self-manipulated variables as output to the original code/page/method that called it? Later, in that same cshtml page, I could reference the new values of provider and providerUserId? – VoidKing Apr 01 '13 at 21:45
  • @VoidKing You are on the right track - It's passing "placeholders" for the method to store values. See my update for an equivalent if C# allowed multiple return values. – D Stanley Apr 01 '13 at 21:48
  • Ah, how useful that could be... So I need only one `return;` statement, and it will just know (based on the 'out' arguments that were passed to it) to return all of the appropriate values? – VoidKing Apr 01 '13 at 21:49
  • @VoidKing I'm not sure I understand - you can change the _values_ any way you like, but it does not affect the _method_ that produced those values. In other words if you change the `provider` value, then call the method again, you will not get a different value back for `provider`. – D Stanley Apr 01 '13 at 21:51
  • @VoidKing You _can_, but be aware that most C# coding guidelines frown on the use of `out` parameters unless absolutely necessary. They are often an indication that a class is doing too much - if you need to return multiple values it's often cleaner to create a class to store those values. – D Stanley Apr 01 '13 at 21:52
  • Okay, thank you, I will, indeed be cautious of this. One last question: I've created many classes, but what would lead one to (not to mention 'how' would one) create a class to store variables? Like, as an object you mean? That I would understand. – VoidKing Apr 01 '13 at 21:57
  • That was probably confusing. I mean creating a class to store values would be like making a class to reference the paramaters of its instantiation? – VoidKing Apr 01 '13 at 21:59
1

Since you don't know what passing argument by reference means Ill start with this.

Usually, when calling a function, you will do so passing parameters by value. That means you are sending values as parameters, not variables.

So if I call:

a = 10;
some_func(a);

That's basically the same as calling:

some_func(10);

Since you are actually sending the value contained in a and not the actual variable a.

But what if you wanted your function to actually change the value in a? In this case you need to send the argument of the function as a reference so the variable itself is provided to the function. Here is an example:

void sum( int a, int b, ref int c )
{
    c = a + b;
}

As you can see in the function above, the function is receiving a and b by value, because it does not intend on changing them. But c is passed by reference, because we intend to put the result of the function in this variable.

Now to the difference between ref and out.

If you try to call the function above, you might get a compilation error telling you you are sending an uninitialized variable to the function.

But that should not be an issue (in this case) because my referenced variable is actually an output so I don't really care what was the previous value stored in it.

So instead of declaring this variable with the ref keyword, I can use out keyword and that let's the compiler know this variable is only an output so it does not need to check if it has been initialized

Rafael Dazcal
  • 355
  • 1
  • 6
  • Freaking awesome answer! (Not that D Stanley's isn't) So, if I used ref, I would have to have declared it, thus establishing some value, a value I could both reference and manipulate within the method, but with out I don't have to declare anything, as I won't be referencing a value, just setting it and then passing it out? – VoidKing Apr 01 '13 at 21:55
  • You need to declare the variable you are sending (by reference) in both cases. The difference is that with out keyword, the variable can be uninitialized, meaning that you don't care the initial value in it before you pass it to the function – Rafael Dazcal Apr 01 '13 at 22:12