Quantcast
Channel: Matt Davey » C# Best Practices
Viewing all articles
Browse latest Browse all 6

A word of caution when overriding operators on reference types

$
0
0

Recently I came across this little snippet of code which contains a serious gotcha!

public class Foo
{
    public Int32 Amount { get; private set; }

    public Foo(Int32 amount)
    {
        Amount = amount;
    }

    static public Foo operator +(Foo x, Foo y)
    {
        x.Amount += y.Amount;

        return x;
    }
}

This has two problems. Firstly the operator is mutating one of the operands, which is a side effect which probably wasn’t intended by the calling code. Secondly, the operator is returning a reference to one of the operands, which is likely to lead to serious and hard to track down bugs in the calling code. Take this simple usage example:

var x = new Foo(10);
var y = new Foo(20);
var sum = x + y;

Console.WriteLine(x.Amount);
Console.WriteLine(y.Amount);
Console.WriteLine(sum.Amount);

You might expect the output to be:
10
20
30

But in fact the output is:
30
20
30

The operator has mutated ‘x’ and returned a reference to it, such that ‘x’ and ‘sum’ are both referencing the same object.

The operator should be re-written like so:

static public Foo operator +(Foo x, Foo y)
{
    return new Foo(x.Amount + y.Amount);
}

To summarize, remember these two simple rules when overriding operators on reference types

  • Do not mutate any of the operands.
  • Do not return a reference to any of the operands.


Viewing all articles
Browse latest Browse all 6

Trending Articles