Home > OS >  Test not compiling - operator overrides in C#
Test not compiling - operator overrides in C#

Time:10-23

I'm using a struct with 2 properties, and I'm overriding some operators in order to compare, add and subtract them on the basis of their 'amount'.

public struct CurrencyAmount
{
    private decimal amount;
    private string currency;

    public CurrencyAmount(decimal amount, string currency)
    {
        this.amount = amount;
        this.currency = currency;
    }

    public static decimal operator  (CurrencyAmount amount1, CurrencyAmount amount2)
    {
        if (amount1.currency != amount2.currency) throw new ArgumentException();
        return amount1.amount   amount2.amount;
    }
    public static decimal operator -(CurrencyAmount amount1, CurrencyAmount amount2)
    {
        if (amount1.currency != amount2.currency) throw new ArgumentException();
        return amount1.amount - amount2.amount;
    }

My problem is that this test doesn't compile:

    [Property]
public void Addition_with_same_currency(decimal value1, decimal value2)
{
    var amount1 = new CurrencyAmount(value1, "HD");
    var amount2 = new CurrencyAmount(value2, "HD");
    var expected = new CurrencyAmount(value1   value2, "HD");

    Assert.Equal(expected, amount1   amount2);
}

I get a CS1503 error : Argument 1: cannot convert from 'CurrencyAmount' to 'string' and Argument 2: cannot convert from 'decimal' to 'string', from the 'expected' and 'amount1 amount2' parameters respectively.

but this test compiles and passes:

    [Property]
public void Addition_is_commutative(decimal value1, decimal value2)
{
    var amount1 = new CurrencyAmount(value1, "HD");
    var amount2 = new CurrencyAmount(value2, "HD");

    Assert.Equal(amount1   amount2, amount2   amount1);
}

So the addition operator appears to be overridden properly. What am I missing here?

CodePudding user response:

amount1 amount2 returns a decimal and then you are basically trying to equate a CurrencyAmount with a decimal.

I would suggest making the operator return a new CurrencyAmount:

public static CurrencyAmount operator  (CurrencyAmount amount1, 
    CurrencyAmount amount2)
{
    if (amount1.currency != amount2.currency) throw new ArgumentException();
    return new CurrencyAmount(amount1.amount   amount2.amount, amount1.currency);
}

Another option would be to create an == operator that takes a decimal, though you would lose the currency type check:

public static bool operator ==(CurrencyAmount amount1, decimal amount2)
{
    return (amount1.amount == amount2);
}

public static bool operator !=(CurrencyAmount amount1, decimal amount2)
{
    return (amount1.amount != amount2);
}

And now you could do:

Assert.True(expected == (amount1   amount2));

CodePudding user response:

The reason it is failing to compile is because Assert.AreEqual requires two objects of the same type. You are passing it a CurrencyAmount and a decimal, which are different types.

While DavidG's answer is correct, there is a simpler solution, although it requires you to change the access modifier of CurrencyAmount.amount. What is the point of a struct with all private members anyway?

My best guess from your code is that you want something like this:

   public struct CurrencyAmount
    {
        public decimal Amount { get; }
        public string Currency { get; }

        public CurrencyAmount(decimal amount, string currency)
        {
            Amount = amount;
            Currency = currency;
        }

        public static decimal operator  (CurrencyAmount amount1, CurrencyAmount amount2)
        {
            if (amount1.Currency != amount2.Currency) throw new ArgumentException();
            return amount1.Amount   amount2.Amount;
        }
        public static decimal operator -(CurrencyAmount amount1, CurrencyAmount amount2)
        {
            if (amount1.Currency != amount2.Currency) throw new ArgumentException();
            return amount1.Amount - amount2.Amount;
        }
    }

    [Property]
    public void Addition_with_same_currency(decimal value1, decimal value2)
    {
        var amount1 = new CurrencyAmount(value1, "HD");
        var amount2 = new CurrencyAmount(value2, "HD");
        var expected = new CurrencyAmount(value1   value2, "HD");

        Assert.Equal(expected.Amount, amount1   amount2);
    }

Also, I think you made a typo by defining the - operator as -=.

  • Related