0

I have function that changes argument of List type (changes inner object state). For example:

    public void ChangeList<T>(List<T> source, T value)
    {
        //Actions
        source.Add(value);
        //Actions
    }

What is the function signature is better? And why?

First: public void ChangeList<T>(List<T> source, T value)

or

Second: public void ChangeList<T>(ref List<T> source, T value)

Edit: The question can be changed. How to explicitly specify that the function changes the state of the list? (except function name or ReadonlyCollection)

Evgeniy Mironov
  • 777
  • 6
  • 22
  • 1
    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-sharp) – M.kazem Akhgary Nov 30 '15 at 16:35
  • 4
    Like Marc answered, using `ref` (or not using it) isn't a "coding style". A coding style is preferring 2 spaces instead of a 1 tab, or using `{ }` for single-line `if` statements. `ref` has a functional behavior and is used depending on the context of the method. Read and learn what `ref` does on MSDN and decide if you need it or not: https://msdn.microsoft.com/en-us/library/14akc2c7.aspx – sab669 Nov 30 '15 at 16:35
  • Check this thread. http://stackoverflow.com/questions/4311226/list-passed-by-ref-help-me-explain-this-behaviour The answer (graphical) below the actual marked one is better to understand. – Nikhil Vartak Nov 30 '15 at 16:39

3 Answers3

8

The first one. The second one screams "I don't know what ref means"; it is simply wrong here. This isn't even a style question, really. The only reason to use ref in this context is if the ChangeList method needed to reassign the list (returning a different list instance, rather than doing what the name suggests, and mutating the existing list). And in that scenario, I think a return would be better:

public List<T> TransformBasedOnList<T>(List<T> source, T value) { ... }
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
0

You should Use ref only when you are changing reference of List: e.g.

public void ChangeList<T>(ref List<T> source, T value)
{
    //Actions
    source = new List<T>; // or initialize using API/DB call
    source.Add(value);
    //Actions
}
Chirag Rupani
  • 1,675
  • 1
  • 17
  • 37
0

Expanding on my comment, see this sample application that showcases the difference between passing an argument by ref:

static void Main(string[] args)
{
    int val = 1;
    int val2 = 1;

    Add(ref val);
    Add(val2);
    Console.WriteLine("Add 44 to Refence of val: " + val);
    Console.WriteLine("Add 44 to i, not by ref:  " + val2);

    Console.ReadKey();
}

static void Add(ref int i)
{
    i += 44;
}

static void Add(int i)
{
    i += 44;
}

Output:

enter image description here

As you can see, when passing a value by ref, you change the value "outside" of the scope of the called method. The calling method is aware of these changes. Basically, the called method "has a reference to that variable's memory location" and that location has a value assigned. I do have a type-o in my console output, that should say Add 44 to val2, not by ref:

When you don't use ref, the change doesn't get "recognized" outside of the scope of the method that was called. Instead it's passed the value of the argument / parameter, the actual memory reference is disregarded and only the method's local value is changed.

Not a very good explanation, truthfully my vocabulary isn't spectacular in this matter (and I'd love it if someone could correct me!) but I think the example is simple enough and the screenshot clearly shows the differences.

Edit: Also, just re-linking MSDN:

https://msdn.microsoft.com/en-us/library/14akc2c7.aspx

And pointing out this important note as well,

Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by ref regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference.

A "reference type" is basically just a type that only refers to a memory location, so you could have 2 reference types that refer to the same object instance. A "value type" directly contain the actual value and you can't mess up one value type's value by modifying a different value type; they're two separate instances that just happen to have the same value. However, using ref, you can make value types behave in a fashion similar to reference types.

Think of it like saying, "Get the coat on the third hook"- that's a reference. You know where a coat is, it's reference. If you said, "Get my coat" you know exactly what coat (value) you're getting.

sab669
  • 3,984
  • 8
  • 38
  • 75