views:

304

answers:

7

When a C# function has an output parameter, you make that clear as follows:

private void f(out OutputParameterClass outputParameter);

This states that the parameter does not have to be initialized when the function is called. However, when calling this function, you have to repeat the out keyword:

f(out outputParameter);

I am wondering what this is good for. Why is it necessary to repeat part of the function specification? Does anyone know?

A: 

you probably have to say out so its clear, if not you wouldnt know without looking at the method signature i guess..

Daniel
The example you've got doesn't work due to the definite assignment differences between out and ref.
Jon Skeet
+23  A: 

It means you know what you're doing - that you're acknowledging it's an out parameter. Do you really want the utterly different behaviour to happen silently? The same is true for ref, by the way.

(You can also overload based on by-value vs out/ref, but I wouldn't recommend it.)

Basically, if you've got an (uncaptured) local variable and you use it as a non-out/ref argument, you know that the value of that variable won't be changed within the method. (If it's a reference type variable then the data within the object it refers to may be changed, but that's very different.)

This avoids the kind of situation you get in C++ where you unknowingly pass something by reference, but assume that the value hasn't changed...

Jon Skeet
Exactly. It can cause huge headaches if your variable is unconsciously changed by the callee.
Mehrdad Afshari
Here here! PHP "return by reference" (or passing parameters by reference, same thing) let you ignore the "by reference" by excluding the ampersand at the point of assigning the return value. Talk about an insanely maddening bug to find when all you left out is an ampersand somewhere. Requiring "out" in C# is the sanest way to avoid such bugs.
Colin Burnett
As a curiosity, why is it not recommended to have an overload on out? Does it has an impact on performance, or it is for readability?
Pierre-Alain Vigeant
@Mehrdad: in C# all class instances are passed by reference.
Dimitri C.
"This avoids the kind of situation you get in C++ where you unknowingly pass something by reference": in C++, most function parameters should be marked as "const". In such a case, you are (almost) certain that you variable won't be modified.
Dimitri C.
@Dimitri: No they're not. The reference is passed by value. There's a *huge* difference. Please read http://pobox.com/~skeet/csharp/parameters.html
Jon Skeet
@Dimitri: You only know about the const if you check the signature, in which case you already know it's by-ref.
Jon Skeet
Dimitri C: To quote Jon: "Objects are not passed at all. References are passed by value."
Mehrdad Afshari
@Pierre-Alain: Overloading can get confusing enough as it is. Overloading by such a relatively subtle thing as how the parameter is passed is almost bound to cause confusion.
Jon Skeet
If the "out" keyword needs to be duplicated, wouldn't it be better that you would have to duplicate the parameter types also?
Dimitri C.
@Dimitri: Those are already enforced by the compiler by static typing - the argument type has to be implicitly convertible to the parameter type, or in the case of ref/out they have to be exactly the same type.
Jon Skeet
The MOST important reason for the repeating of out/ref is that if the function you're calling gets refactored with a different signature, you will get a compile error. Most notably, if a parameter goes from non-out to out, you'll know right away.
plinth
@Jon, @Dimitri C.: Also, the *readers* of the calling code may not know about out/ref in the function signature. On the other hand, parameter types will be easily inferred by knowing the types of the actual parameters.
Daniel Daranas
@plinth: that is a very good remark. I hadn't thought about that! Wouldn't it be better to post that as an answer?
Dimitri C.
In my opinion, if this duplication serves *only* for clarity, it merely increases verboseness. However, I think plinth's remark is to the point, as it aids refactoring.
Dimitri C.
@Dimitri C. I think it *does* increase clarity.
Daniel Daranas
@Dimitri: Bear in mind that this duplication isn't (often) between two bits of code in the same file. It's between a method parameter which you may not even have the source for, and the method argument you happen to be looking at. Personally I like to be able to understand pretty much what code will do without having to look up every signature to check if it has any ref/out parameters.
Jon Skeet
+1  A: 

The only reason I can see is to make sure the user of the function knows that the value of this parameter can be modified by the function. I think it's a good thing.

mberube.Net
Not only it can be modified - it *will* be modified.
Daniel Daranas
Daniel: Not really. It can leave the function unmodified. `out` is enforced by the compiler. If the declaring function is written in another language, it might choose not to enforce definite assignment.
Mehrdad Afshari
In another language? Which one?
Daniel Daranas
For example, you craft your own function in IL and decorate it with `out` attribute. Then you'll have a C# method call it.
Mehrdad Afshari
How typical :] Well, in any case, the out parameter in C# (which was the question's tag) *must* be assigned to in the function. Of course you may try to jump around it, but I don't see much sense in using this kind of modifiers (out, ref) without respecting their semantics.
Daniel Daranas
+1  A: 

While I don't know the origin of such decision, I know that it has a purpose for overloading.

It is totally legal to create these two functions in the same class:

private void f(out OutputParameterClass outputParameter);

and

private void f(OutputParameterClass outputParameter);

Specifying the out keyword when calling such overload make sense.

Pierre-Alain Vigeant
+1  A: 

I think it's a matter of consistency and clarity.

Clearly, the compiler could do well without. However, with the out keyword added, you're making your intentions clear, and the code gets clearer and more legible.

Tor Haugen
+1  A: 

For readability, knowing what the method can/will do to your variable.

Got some more info from MSDN: http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx

The caller of a method which takes an out parameter is not required to assign to the variable passed as the out parameter prior to the call; however, the callee is required to assign to the out parameter before returning.

Zenuka
+1  A: 

The best answer I got was posted as a comment by plinth:

The most important reason for the repeating of out/ref is that if the function you're calling gets refactored with a different signature, you will get a compile error. Most notably, if a parameter goes from non-out to out, you'll know right away.

Dimitri C.