Skip to Content
Course content

63: Operator Overloading in C#

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've seen this happen to almost every developer the first time they try to build a physics engine or a coordinate system in C#. You've got two objects that represent a mathematical concept, and it feels completely natural to just "add" them together. But then you hit a wall with a compiler error that feels like the language is being stubborn.

public class Vector2
{
    public double X { get; set; }
    public double Y { get; set; }

    public Vector2(double x, double y)
    {
        X = x;
        Y = y;
    }
}

// Somewhere else in the code...
Vector2 position = new Vector2(10, 20);
Vector2 velocity = new Vector2(5, -2);

// This line triggers: Operator '+' cannot be applied to operands of type 'Vector2' and 'Vector2'
Vector2 newPosition = position + velocity; 

The "Operator cannot be applied" Error

The issue here is that C# is a strongly typed language. While the + operator knows exactly what to do with two integers or two strings, it has no clue what "adding" two Vector2 objects means. Should it add the X values? The Y values? Should it multiply them? The compiler won't guess; it expects you to define the behavior explicitly.

You might be tempted to just write a method like position.Add(velocity). That works, but it's clunky. When you're doing heavy math, a + b + c is significantly more readable than a.Add(b).Add(c). This is where operator overloading comes in.

Defining Custom Addition Logic

To fix this, we need to tell C# how to handle the + symbol when it sees two Vector2 instances. We do this by defining a public static method using the operator keyword.

public class Vector2
{
    public double X { get; set; }
    public double Y { get; set; }

    public Vector2(double x, double y)
    {
        X = x;
        Y = y;
    }

    // This is the operator overload
    public static Vector2 operator +(Vector2 left, Vector2 right)
    {
        return new Vector2(left.X + right.X, left.Y + right.Y);
    }

    public static Vector2 operator -(Vector2 left, Vector2 right)
    {
        return new Vector2(left.X - right.X, left.Y - right.Y);
    }
}

Notice two critical things here: the method must be public static, and it must return a value of the type being operated on (or another compatible type). Now, that position + velocity line will compile and execute exactly as you'd expect.

The Pairing Requirement for Equality

Overloading arithmetic operators is straightforward, but equality operators (== and !=) have a stricter rule: they must be overloaded in pairs. If you overload ==, the compiler will throw an error if you haven't also overloaded !=. It's a safety mechanism to ensure your object's logic remains consistent.

I also highly recommend that if you overload ==, you should override Equals() and GetHashCode(). If you don't, you'll run into a nightmare scenario where vecA == vecB returns true, but vecA.Equals(vecB) returns false because it's still using the default reference equality check.

public override bool Equals(object obj)
{
    if (obj is Vector2 other)
    {
        return this.X == other.X && this.Y == other.Y;
    }
    return false;
}

public override int GetHashCode() => HashCode.Combine(X, Y);

public static bool operator ==(Vector2 left, Vector2 right)
{
    if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
        return ReferenceEquals(left, right);
        
    return left.X == right.X && left.Y == right.Y;
}

public static bool operator !=(Vector2 left, Vector2 right)
{
    return !(left == right);
}

One pro tip: inside the == overload, I used ReferenceEquals instead of left == null. If you use left == null inside the == overload, you'll create an infinite recursive loop that crashes your program with a StackOverflowException. Always be careful with null checks inside operator overloads.




📋 Practical Task

Implementing a Complex Number Arithmetic Suite

In mathematics, complex numbers consist of a real part and an imaginary part (e.g., 3 + 4i). Your task is to create a ComplexNumber class that allows these numbers to be manipulated using standard operators.

Requirements:

  • Create a class ComplexNumber with two double properties: Real and Imaginary.
  • Overload the + operator to add two complex numbers (Add real to real, imaginary to imaginary).
  • Overload the - operator to subtract two complex numbers.
  • Overload the == and != operators to compare two complex numbers based on their values.
  • Override Equals() and GetHashCode() to ensure consistency with the equality operators.

Testing your code:

Instantiate two complex numbers: c1(3, 2) and c2(1, 7). Use the + operator to create c3. Verify that c3.Real is 4 and c3.Imaginary is 9. Then, verify that c1 == c2 returns false.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.