Tech Off Post

Single Post Permalink

View Thread: differnence between Ref and Out
  • User profile image
    Sven Groot

    As BitFlipper said, with out the method is required to set a value before it returns.

    // This function won't compile because value isn't set on all code paths
    void Foo(out int value)
    {
    }
    
    // Whereas this is fine even though value isn't set.
    void Bar(ref int value)
    {
    }

    It also makes a difference on the calling side, however. Out parameters don't need to be initialized before passing them to a function:

    void Test()
    {
        int n;
        SomeFunc(ref n); // This won't compile; n is uninitialized.
        SomeOtherFunc(out n); // Whereas this is fine, even if n is uninitialized
        // n is guaranteed to have a value after the call to Foo, because
        // the function is required to assign it a value before returning.
    }

    Basically, use ref when you need to pass a value in and get a different value out, and use out when you only need to get a value out.

    In general, try to avoid using ref/out parameters, because they lead to code that doesn't compose well. Sometimes it's unavoidable, but always try to find an alternative solution.

    Just in case (since this is a common point of confusion): you do not need to use ref to be able to modify a parameter of a reference type (class) inside a function. With reference types you already passing a reference. Passing a reference type with ref means you pass a reference to a reference, which is only needed if you want to return a completely different instance to the caller.

    class Foo
    {
        public string Bar { get; set; }
    }
    
    void ModifyFoo(Foo value)
    {
        value.Bar = "hello"; // The caller will see this change, even without ref
        value = new Foo(); // But the caller will *not* see this change; it doesn't get the new instance.
    }
    
    void ReplaceFoo(ref Foo value)
    {
        value = new Foo(); // With ref, the caller will see this change and get the new instance.
        // I could've used out here, since we don't use the value that was passed in.
    }