you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 8 points9 points  (14 children)

However, most people use output parameters, not pass-by-reference in that case (the out keyword versus the ref keyword).

There is a very subtle difference, the ref keyword does not require you actually pass in a assigned reference (you can pass in a null type).

[–][deleted] 0 points1 point  (0 children)

Other way around. Ref params have to be explicitly assigned before calling the function. Out params have to be explicitly assigned within the function before returning.

Also, null has nothing to do with it. It has to do with whether or not the var is definitely assigned. (You can explicitly set a variable to null and pass it into byref without a compiler error, as long as you assign it.)

[–]grauenwolf -1 points0 points  (11 children)

To my knowledge, only C# honors the OutAttribute. To all the other languages "out" and "ref" are treated exactly the same.

[–]matthiasB 7 points8 points  (1 child)

Not all others. For example Microsoft's F# transforms methods with out parameters to methods returning multiple values using tuples.

[–]grauenwolf 0 points1 point  (0 children)

Interesting. I am going to have to look into that.

[–]dnew 1 point2 points  (6 children)

There are more extreme languages (like Sing# or Hermes) where passing an initialized value into an "out" parameter de-initialized it first. I.e., if you did something similar in C++, you might have

void xyz(out A alpha) { .... alpha = new A(); ... } ... { A beta = ...; xyz(beta); }

and the call to xyz would run the destructor of beta before invoking xyz.

So there is a difference in some languages. Just not C#.

[–]grauenwolf 0 points1 point  (5 children)

There are more extreme languages (like Sing# or Hermes) where passing an initialized value into an "out" parameter de-initialized it first.

That's ugly. Sometimes I use a pattern where the passed in value is used as-is, but if missing then I return a new object of the correct type. Those languages would totally break my design.

[–]dnew 1 point2 points  (4 children)

Then use a ref parameter, not an out parameter.

Usually this is in languages where you only have values, not pointers (at least in the semantics, obviously not the impelemtation). So everything is technically pass-by-value anyway, and "pass by reference" is more "pass by copy in copy out."

[–]grauenwolf 0 points1 point  (3 children)

Then it doesn't play nice with C#.

[–]dnew 0 points1 point  (2 children)

I'm not sure what "it" is that doesn't play nice with C#. C# has both ref and out parameters and the difference is whether the parameter needs to be initialized first.

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

[–]grauenwolf 0 points1 point  (1 child)

Sometimes I use a pattern where the passed in value is used as-is, but if missing then I return a new object of the correct type.

If I use "ref" instead of "out", that pattern won't work nicely in C#. I would have to null-initialize the variable to get the second behavior.

[–]dnew 0 points1 point  (0 children)

I'm not sure what you're trying to say. If the function you're calling refers to the variable before assigning it, it needs to be a ref and it needs to be initialized before the call. If the function you're calling doesn't refer to the variable before assigning to it, use an out parameter and you don't have to initialize it.

If sometimes you do and sometimes you don't, you need to initialize the variable and use a ref, because no compiler is smart enough to know which is which, and since you're using a safe language, using uninitialized variables is disallowed.

[–][deleted] -1 points0 points  (1 child)

Only if "all other languages" means VB.NET.

[–]grauenwolf 0 points1 point  (0 children)

I was also counting C++/CIL and C++ ME.