0

I see sometimes method that has a parameter, modifies it and returns it. Is there any advantage of that, why no simply pass the parameter by ref and keep the method by ref?

Here is what I see:

public MyClass DoSomething(MyClass myClass)
{
    myClass.Amount = 500;
    return myClass;
}

Why not keep it simple like this:

public void DoSomething(ref MyClass myClass)
{
    myClass.Amount = 500;
}
Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
st_stefanov
  • 1,147
  • 1
  • 10
  • 28
  • 3
    ref MyClass myClass has no much sense if myClass is a class, that has sense if myClass is a struct. – Stefano Balzarotti Dec 03 '19 at 12:30
  • You don't need to add ref in second method. – apocalypse Dec 03 '19 at 12:30
  • 4
    @StefanoBalzarotti Actually `ref` makes sense if you want to overwrite the instance. – DavidG Dec 03 '19 at 12:37
  • "I see sometimes method that has a parameter, modifies it and returns it" such a construct actually makes it quite obvious that a change to the object was made when you read the code. you don't need to dive into the method to see what it does if you see a line like `x = DoSomething(x)` – Mong Zhu Dec 03 '19 at 12:49
  • 2
    Here's a good blog by Jon Skeet that covers reference types and how that's different from passing by reference https://jonskeet.uk/csharp/parameters.html – juharr Dec 03 '19 at 12:51
  • 1
    Yes, that way you can chain them up: `MyClass x = myClass.DoSomethingA ().DoSomethingB ().DoSomethingC ()` - Note however, there is no reason to provide the instance as parameter if the method is within the class... unless it's a static extension method. – Battle Dec 03 '19 at 13:18

3 Answers3

3

Using the ref keyword only makes sense if you intend to change the reference of your parameter. In general, you want to avoid this, but if you feel like you must:

public class MyClass 
{
    public int Id { get; set; }
    public int Amount { get; set; }
}

Let's say the myClass parameter has Id = 1, Amount = 300.

This works:

public void DoSomething(MyClass myClass) 
{
    myClass.Amount = 500;
}

myClass.Amount has become 500.

This does NOT work:

public void DoSomething(MyClass myClass) 
{
    myClass = new MyClass()
    {
         Id = 5,
         Amount = 500
    }
}

myClass.Amount is still 300 and myClass.Id is 1.

But, this DOES work:

public void DoSomething(ref MyClass myClass) 
{
    myClass = new MyClass()
    {
         Id = 5,
         Amount = 500
    }
}

myClass.Amount is 500 and myClass.Id is 5.

igg
  • 2,172
  • 3
  • 10
  • 33
2

If MyClass is reference type in sample below

public MyClass DoSomething(MyClass myClass)
{
    myClass.Amount = 500;
    return myClass;
}

it doesn't make sense to return it, because all reference types are passed by reference and you can do something like that

public void DoSomething(MyClass myClass)
{
    myClass.Amount = 500;
}

It makes sense only when MyClass is value type (inherits struct).

However, there is new type ref structs introduced in .NET Core, which is used to allocate a struct type in a stack and pass them by reference, not by value (without copying). You can read at documenation

Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
1

As mentioned, if MyClass is reference type, ref doesn't make much sense.

But returning passed argument makes sense, because it returns explicitly modified parameter, so it works for structs and classes. And is more readable, which is very good thing.

Also, if we're talking about reference types, ref is unnecessary and code without it is cleaner.

Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
  • 4
    Actually, it can make sense if you want to allow the method to overwrite the entire object with a new one. – DavidG Dec 03 '19 at 12:39