Search code examples
c#optimizationrefc#-7.0c#-7.2

Should we always return by ref if we can?


Now with C# 7, we can return by ref with return ref. From what I've gathered, references are 32 or 64 bits. Now, if I had a struct Coord with a long X and long Y, that would be 128 bits, so it'd be easier return the coord, (as well as pass it) by reference to avoid copying the 128 bits.

On the other hand, if I were to try to return ref a byte, which is only 8 bits, the reference to it would be much larger than copying byte itself, right?

So, my main question: If the object we want to return can be returned by ref (ie, not a local variable) and its size is larger than the size of a reference, should we return by ref?

Edit: Quick code example

// This size is 128 bytes, which is 2 or 4x larger than the size of a reference
public struct Coord                                 
{
    public long X, Y;
}

private Coord myCoord;

// This will return the Coord by value, meaning copying the full 128 bytes
public Coord GetCoordValue() => myCoord;          

// This will return the Coord by reference, meaning copying only 32 or 64 bytes
public ref readonly Coord GetCoordRef() => ref myCoord;      

Also, this particular struct is very simple and it's already 2/4x smaller to return by ref.

Edit 2: I made GetCoordRef() readonly so that the caller can't save and change the value of myCoord, thereby preserving encapsulation, though I imagine this still wouldn't be smart to default to using it.


Solution

  • If the object we want to return can be returned by ref (ie, not a local variable) and its size is larger than the size of a reference, should we return by ref?

    (1) No.

    (2) For advanced users only: yes, in precisely those cases where your empirical, accurate profiling data indicates that making this change transforms your program from one that disappoints users into one that delights users.

    Are there programs in the marketplace whose failure or success can be traced back to the couple nanoseconds difference of copying a couple extra bytes being traded for the couple nanoseconds of making a pointer indirection later? I'm not aware of any, but maybe you write programs whose users have very tight budgets for the number of nanoseconds they want your API to take.