2

A coworker and i were debating today whether or not it is ever useful to make this sort of a function:

private void MyFunction(ref MyClass variable)
    {

    }

The only advantage i can see is that it would allow you to set the original pointer to the variable to null... outside of that there would be no difference if you omitted the ref, correct?

Can you think of any reason to ever pass a ref string to a function?

Micah
  • 10,295
  • 13
  • 66
  • 95
  • possible duplicate of [When to use ref and when it is not necessary in C#.](http://stackoverflow.com/questions/635915/when-to-use-ref-and-when-it-is-not-necessary-in-c) – Wim Coenen Nov 16 '10 at 21:03
  • Your method can return only one value. Use it wisely. Having it return void and passing by ref doesn't make a great deal of sense. Unless you want to provide overloads (can't overload on return type). – Hans Passant Nov 16 '10 at 21:42

7 Answers7

5

Personally I'd prefer to return a Tuple with multiple values, but the basic point is to give multiple results to the caller. In the case of a ref parameter, the extra result will potentially replace the value in an existing variable. Note that this is very different to just working on the parameter itself. For example:

public void Foo(ref StringBuilder builder)
{
    builder = new StringBuilder("hello");
}

is completely different to:

public void Foo(StringBuilder builder)
{
    builder.Clear();
    build.Append("hello");
}

Whether the parameter type is a reference type or a value type is somewhat irrelevant - particularly when you consider immutable types such as string, where there's no equivalent to the latter approach above.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • That's what I do - return a `Tuple`. The main reason being that some people might not understand what my code is doing if I start passing `ref` or `out` parameters. Arguments go in, return value comes out - I try to keep it that way. – Nobody Nov 16 '10 at 21:05
  • Returning a Tuple is surely an alternative to an "out" parameter, rather than a "ref" parameter. "ref" parameters are rarely needed, but when they are (e.g. Interlocked.Exchange), returning a Tuple is not a substitute. – Joe Nov 16 '10 at 21:34
2

The TryParse and TryGetValue family of methods?

Get a value and an indication of success, without having to parse/search twice.

I've used this myself to split and address into a street and housenumber. Within the method I have both, if I only have a return value, I would have to split the data twice.

The example you use does not look usefull, except in an interop context.

GvS
  • 52,015
  • 16
  • 101
  • 139
  • 2
    TryParse and TryGetValue do not use *ref* they use *out* which is different in the context of this question. – Stan R. Nov 16 '10 at 21:14
2

Here's a brief example.

private void MyFunction(ref MyClass variable)
{
  variable = new MyClass();
  // You just changed the variable that was passed,
  // even outside the scope of this method!
}

private void MyFunction(MyClass variable)
{
  variable = new MyClass();
  // Without ref, the variable is still intact
  // outside of this scope.
}
jordanbtucker
  • 5,768
  • 2
  • 30
  • 43
  • This definitely answers the OP's question. But please, for the love of god, if you need to do this, just have a return type of "MyClass" – viggity Mar 28 '11 at 14:37
  • @viggity But then you'd need to write `myClassVar = MyFuction(myClassVar)` instead of just `MyFunction(myClassVar)`. – jordanbtucker Mar 29 '11 at 03:09
  • yes, but it will be a lot easier to read and maintain. I don't like calling a method that modifies state to begin with, but swapping out the entire reference without making it explicitly known to the caller is asking for trouble. – viggity Mar 29 '11 at 14:20
1

Sometimes you want to return a value and update an object at the same time:

// Converts specified brush to grayscale. Returns `true` on success,
// or `false` if the brush is already grayscale.
public bool MakeBrushGrayscale(ref SolidBrush brush)
{
    if (IsGrayscale(brush.Color)) {
        return false;
    }

    brush = new SolidBrush(GetGrayscaleColor(brush.Color));
    return true;
}
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • Although in this case you would probably want an out parameter OR you would want to dispose of the brush before you create the new one, no need to leak handles :) – pstrjds Nov 16 '10 at 21:05
  • @pstrjds, `out` parameters might be uninitialized, which would break the first line of the function. You're right about `Dispose()`, but I guess I'll let the GC handle that for the sake of the example :) – Frédéric Hamidi Nov 16 '10 at 21:07
  • good call on the out parameter, should have thought that through further. I am paranoid with the Brushes and other objects in the System.Drawing space, have run across programs crashing due to leaked GDI handles, so I like to ensure Dispose is called on those objects. Still a solid example of when someone may want to use a ref parameter so the object passed in is modified. Gotta love side effects! – pstrjds Nov 16 '10 at 21:13
1

Sometimes you might want to change the object reference. Imagine a method called Reload(object o) that reloads an object with the data from the database. You can get a new instance of the object from your data access layer (different from the original reference - it does not support identity map) and need to return it to the user.

You have 2 choices here:

object Reload(object o)
{
    return dao.GetById(IdHelper.GetId(o));
}

or

void Reload(ref object o)
{
    o = dao.GetById(IdHelper.GetId(o));
}

Some people might consider the former to be a better design. However, it has a problem. Developers using it might forget to assign the return value to the variable thinking that the object passed into the method will be changed. The ref attribute makes it impossible to use the second method version incorrectly.

Dmitry S.
  • 8,373
  • 2
  • 39
  • 49
0

I can't argue this is a good reason, but if you were going to pin it and manipulate the raw data of the string (maybe your function is passing it off to some encryption method that is swapping the characters around).

pstrjds
  • 16,840
  • 6
  • 52
  • 61
0

I think that using ref everywhere is bad practice.

  1. Good practice is don't give more than necessary.
  2. When you use ref you cann't pass null to the method.
acoolaum
  • 2,132
  • 2
  • 15
  • 24