Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# implicitly updates parameter passed to method with no return type and no out or ref usage

Tags:

c#

This is so funky to me, obviously the developer should have used the keyword out but I can't believe this is even working:

public BusinessResponse<MyResultType> MyMethod(){

    BusinessResponse<MyResultType> res = new BusinessResponse<MyResultType>();
    ProcessResult(res);

    return res; //this has the values set by ProcessResult!!! How?
}

private void ProcessResult(BusinessResponse<MyResultType> result)
{
    result.State = BusinessResponseState.Success;
    //set some other stuff in the result argument
}

My coworker said this is called "deep reference", I can't believe this works in C#. I would refactor to use out aka private void ProcessResult(out BusinessResponse<MyResultType> result) but I would still like to know why this code works.

UPDATE

So it looks like I am incorrect and this code is just fine. Seems the sentiment is, that as a C# developer I should immediately know, since the argument passed into processResult is a reference type on the heap being passed in by value that a copy of the reference itself is made and that copied reference still points to the same object.

like image 542
Brian Ogden Avatar asked Jan 23 '14 00:01

Brian Ogden


1 Answers

Certainly in your case BusinessResponse<T> is a class, also known as a "reference type". Reference types (objects) are always passed "by reference" in C#, (akin to a pointer in good ol' C)1.

This means that no matter how you pass a reference around, it is still referring to the one instance in memory. Which means no matter how you refer to it, you're always modifying the same copy.

1 - That's not entirely true. What actually happens is the reference (variable) is passed by value. When the function receives this reference (again, think of a pointer to some object out on the managed heap), it is refering to the same object. However, the reference itself was copied when it was passed in.

The other kind of variable we use is a "value type". These are structs, as well as all of the primitives like char, bool, int, etc. These are unsurprisingly always passed by value, meaning a copy is made every time you assign a value type to a new variable (which includes passing it to a function). For these to be modified via a function call, you have to use the ref or out keywords.

So when would you use ref with reference types?

When you want to change which instance a variable refers to:

public class Foo {
    public string Name { get; private set; }
    public Foo(string name) {
        Name = name;
    }
}

public class Program {

    public static void Example(ref Foo f) {
        // This will print "original"
        Console.WriteLine("Example() was given {0}", f.Name);

        // We assign a new instance to the reference which was
        // passed by reference
        f = new Foo("replacement");
    } 

    public static void Main() {
        Foo f;                       // This variable is a "reference" to a Foo

        f = new Foo("original");     // We assign a new instance to that variable

        Example(ref f);

        // This will print "replacement"
        Console.WriteLine("After calling Example(), f is {0}", f.Name);
    }

}
  • MSDN: Value Types and Reference Types
like image 172
Jonathon Reinhart Avatar answered Oct 13 '22 13:10

Jonathon Reinhart