views:

533

answers:

10

Apparantly, they're "confusing". Is that seriously the reason? Can you think of any others?

+6  A: 

Have you seen how many developers don't really understand ref/out?

I use them where they're really necessary, but not otherwise. They're usually only useful if you want to effectively return two or more values - in which case it's worth at least thinking about whether there's a way of making the method only do one thing instead. Sometimes using ref/out is the most appropriate approach - the various TryParse methods etc.

Jon Skeet
Amen. I went on a C# training course years ago and there were a bunch of "developers" in the group who just couldn't get their heads around ref/out.
Stewart Johnson
I guess that bunch of "developers" have never had to understand what pointers were.
Alexandre Brisebois
I mainly use ref/out for performance; there's no way in hell that copying a 256 byte structure 105840000 times a second is acceptable ;)
TraumaPony
Why have you got a 256 byte structure in the first place?
Jon Skeet
It's a container of four 4x4 matrices.
TraumaPony
+1  A: 

ref/out automatically means mutability, and functional programming with immutable values is all the rage these days. Try inserting a call to Dictionary.TryGetValue into a LINQ query. The API requires declaring variables and ruins any 'fluency' in the API.

That's not to say this is "the reason", but it is an example of "a reason".

(See also

http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!181.entry

for commentary on how functional languages deal with such APIs.)

Brian
ref/out implies mutability of variables, but not necessarily data types. (I typically use it with local variables, for example.) Fluency is interesting - TryXXX tends to require different behaviour for different branching, which doesn't really go with fluency :(
Jon Skeet
+1  A: 

ref/out also don't work with "Func" delegates, so these style APIs are less composable/reusable with some other APIs that use delegates.

Brian
+2  A: 

Confusing is probably the best reason. Confusing means decreased maintainability and increased likelyhood on introducing subtle bugs. I see them in a similar view to the "goto" control flow statement. While it is not inherently bad on its own accord, it has lead to many many impossible to read / understand programs over the decades.

Stay away from anything that can make your code more confusing then it needs to be.

Having said that, those keywords exist probably because the framework developers saw need for such things. Use them if there is no suitable workaround, but avoid them when you can.

Samuel Kim
+1  A: 

In my opinion, they are considered a code smell because in general there is a much better option: returning an object.

If you notice, in the .NET library they are only used in some special cases, namely tryparse-like scenarios where:

  • returning a class would mean boxing a value type
  • the contract of the method requires it to be fast, and so boxing/unboxing is not a viable option.
Sklivvz
A: 

Isn't code complexity reason enough? Compare:

int myValue;
ReadFromSomewhere(ref myValue);

To:

int myValue = ReadFromSomewhere();
Cristian Libardo
How about when you want to return 2 values. It's often easier to just return 2 values, using byref arguments then it is to create an object/struct that will only be used for the single purpose of calling a single function.
Kibbee
True, but I wasn't referring to multiple arguments. Most of the time I would prefer a struct if I were the user of that function.
Cristian Libardo
How is that complex?
TraumaPony
At the basic level it's just because of 2 rows instead of 1. In the multiple return values case it's totally differnt ways of returning information. Have you seen ruby-style multiple return values?def GetCoordinates() return 0, 20endx, y = GetCoordinates();
Cristian Libardo
Jay Bazuzi
A: 

You can fill an object with the values you want to return and just return the object instead of creating ref and out values.

But it's sometimes easier and I think as good to just use ref/out because now you have to declare a new class just for passing a couple values.

Paul Mendoza
A: 

Just a thought, I find ref/out to be useful when the arguments capture the state of execution in target method rather than capturing returned data. Consider a scenario when you want to get an error message from a service that returns Customer object.

Customer GetCustomerById(int id, out string errorMessage);

If this method fails, you would probably return null Customer object or throw an exception. However, if I want to know the cause of error (validation? database?), I would use out argument. errorMessage argument here has nothing to do with data, simply used to capture what's wrong with the method execution.

Personally if I have a method that is expected to return two or more essential data/values, I would rethink the design of my code.

A: 

The reason I was told is the 1.0 GC had problems when ref/out was used. The GC in 2.0 (and probably not 1.1 either) doesn't have those problems so I would normally assume it is a now non-useful legacy.

Joshua
A: 

@TraumaPony It would be fine if you give us an source (URL or something) to this .NET framework guidlines.

Petar Repac
Neil Williams