Posted by: Cirilo Meggiolaro | 02/3/2009

Tip of the day #112 – Custom conversion for custom classes – Operators

Let’s assume we have the following class:

public class Order
{
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public decimal BilledTotal { get; set; }
}

It is a really simple Order class but wouldn’t be nice to have enough flexibility when handling calculations such as sum billed value from two orders using the format order1 + order2 or convert the Order class instance to decimal and have as result the BilledTotal value?

This is possible overloading operator methods on the class level giving you total control over the operations and conversions.

Some important points to pay attention:

  • Operator methods must be public and static;
  • You have to define the return type;
  • You have to type the operator keyword
  • You have to explicitly define which operator is being overloaded;
  • You have to define the parameters.

First task

Sum two orders using the format order1 + order2 and retrieve the sum of the order totals. Based on the points we have checked above, let’s declare the overload for the + operator method:

public static decimal operator +(Order o1, Order o2)
{
    return o1.BilledTotal + o2.BilledTotal;
}

You have noticed that the method is receiving to Order objects as parameters and it is returning a decimal value. On the method body, the calculation is being performed based on the BilledTotal properties for each object. Once you have two instances of Order class, you may sum the order total value using the syntax order1 + order2.

As the same way, if you want to provide a way to subtract two order total values using the syntax order1 – order2, we need to overload the – operator method:

public static decimal operator -(Order o1, Order o2)
{
    return o1.BilledTotal – o2.BilledTotal;
}

Second task

Convert a Order object to decimal, retrieving the decimal BilledTotal property value. The syntax is a little bit different but is easy to implement:

public static implicit decimal operator (Order order)
{
    return order.BilledTotal;
}

Once you have implemented the method overload above you may use the syntax Convert.ToDecimal(order) and the result will be the BilledTotal property value.

Based on the fact that these are operator overloads you may use for other operations like division, multiply and so on.

public class Order
{
    /// Properties
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public decimal BilledTotal { get; set; }

    /// Overloads + operator
    public static decimal operator +(Order o1, Order o2)
    {
        return o1.BilledTotal + o2.BilledTotal;
    }

    /// Overloads – operator
    public static decimal operator -(Order o1, Order o2)
    {
        return o1.BilledTotal – o2.BilledTotal;
    }

    /// Overloads * operator
    public static decimal operator *(Order o1, Order o2)
    {
        return o1.BilledTotal * o2.BilledTotal;
    }

    /// Overloads / operator
    public static decimal operator /(Order o1, Order o2)
    {
        return o1.BilledTotal / o2.BilledTotal;
    }

    /// Custom decimal conversion.
    public static implicit operator decimal(Order order)
    {
        return order.BilledTotal;
    }
}

Running the code

The following code snippet shows a quick example to check the results from the class above:

Order o1 = new Order() { OrderID = 1, OrderDate = DateTime.Now, BilledTotal = 1234.56M };
Order o2 = new Order() { OrderID = 2, OrderDate = DateTime.Now, BilledTotal = 4.99M };
Order o3 = new Order() { OrderID = 3, OrderDate = DateTime.Now, BilledTotal = 999.00M };

decimal billedTotalOrder1 = Convert.ToDecimal(o1);
Console.WriteLine(billedTotalOrder1);

decimal sum = o1 + o2;
sum += o3;
Console.WriteLine(sum);

Console.WriteLine(o1 + o2 + o3);


Responses

  1. Readable code!

    Cirilo I´m curious… Worrying about memory and because we have to pass the whole object around, does it worth overload those methods? Or under the cover the CLR handle with that in a good manner?


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: