Byron Sommardahl
Byron Sommardahl

Reputation: 13012

How to add or subtract two instances of the same class/type

I have a type that represents a type of number. In this case, I'm working with megawatts, so I have created a type called Megawatt. I'd like to be able to work with these megawatts like I would an Int, Double, or any type of c# number type. Is this possible? If so, how do I do it?

Example:

public class Megawatt{
    public double Value { get; set; }
}

I want to be able to do this:

var startOfDay = new Megawatts{value=100};
var endOfDay = new Megawatts{value=65};
Megawatt result = startOfDay - endOfDay;

This is possible with DateTime... you can subtract one DateTime from another and get a TimeSpan. I'm hoping to do something similar.

Upvotes: 19

Views: 8643

Answers (5)

David Sulpy
David Sulpy

Reputation: 2347

Expanded Answer: Operator overloading is the way to go in this case for sure. Overloading operators is a great option in C# that allows convenience of operators in lieu of methods in a class.

When you overload an operator such as + the corresponding compound assignment operator is also overloaded e.g. +=

As you would imagine with their use, operator overloads must be static and use the keyword operator as in @RoyiNamir's answer.

Just to expand on the answer the following binary comparison operators, in addition to mathematical operators, can be overloaded in pairs only:

  1. == and !=
  2. > and <
  3. >= and <=

As far as code design recommendation, just like @RoyiNamir said, the operator overloads should exist inside the class that they are overloading the operators of.

Upvotes: 1

Dour High Arch
Dour High Arch

Reputation: 21722

Creating your own types is a good idea; it prevents Mars lander problems where you add kilograms and pounds. However, I suggest making them structs, not classes, as that will make them immutable and remove the potential of initializing null values. Also, make value private so you can do things like:

var startOfDay = new Megawatts(100);
var endOfDay = new Megawatts(65);
Megawatt result = startOfDay - endOfDay;

You should also consider implementing IComparable<>, IEquatable<>, conversion operators, and so on. This will let you perform comparisons on, and construct collections of, Megawatts.

Doing all of these is a lot of work; consult C# Canonical Forms.

Upvotes: 0

Eric Lippert
Eric Lippert

Reputation: 660327

In addition to the good answers posted so far: you should make your type an immutable struct rather than a mutable value type. This is precisely the sort of job that immutable value types were designed for.

struct Megawatt
{
    private double Value { get; private set; }
    public Megawatt(double value) : this()
    {
        this.Value = value;
    }
    public static Megawatt operator +(Megawatt x, Megawatt y)
    {
        return new Megawatt(x.Value + y.Value);
    }
    public static Megawatt operator -(Megawatt x, Megawatt y)
    {
        return new Megawatt(x.Value - y.Value);
    }
    // unary minus
    public static Megawatt operator -(Megawatt x)
    {
        return new Megawatt(-x.Value);
    }
    public static Megawatt operator *(Megawatt x, double y)
    {
        return new Megawatt(x.Value * y);
    }
    public static Megawatt operator *(double x, Megawatt y)
    {
        return new Megawatt(x * y.Value);
    }
}

And so on. Note that you can add together two megawatts, but you cannot multiply two megawatts; you can only multiply megawatts by doubles.

You could also add more unit-laden types. For example, you could create a type MegawattHour and a type Hour and then say that Megawatt times Hour gives MegawattHour. You could also say that there is another type Joule, and there is an implicit conversion from MegawattHour to Joule.

There are a number of programming languages that support these sorts of operations with less verbosity than C#; if you do a lot of this sort of thing you might look into F#.

Upvotes: 36

Royi Namir
Royi Namir

Reputation: 148634

you should write your own operator overloading :

sample :

   public static Megawatt operator +(Megawatt c1, Megawatt c2) 
   {
      return new Megawatt(c1.value+ c2.value);
   }

Upvotes: 12

devshorts
devshorts

Reputation: 8872

This is called operator overloading. I suggest you read this article:

http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx

It is a tutorial on the process. Basically you change the meaning of the - operator for those types.

As an example (stolen from the link)

public static Megawatt operator -(Megawatt c1, Megawatt c2) 
{
  // do whatever you want here
}

And this way your minus sign can now subtract MegaWatts

You can do this for any type or combination of types. You can even return yet a third type if you wanted to. Many languages support this concept and its quite useful.

Upvotes: 2

Related Questions