C# Academy · Lesson

Overloading Arithmetic Operators

Define +, -, * for your own types.

Lesson 1 of 413 steps

Overloading Arithmetic Operators is a free C# Academy lesson on CoddyKit. This is lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, and your progress syncs across the web and the CoddyKit app. The C# Academy course includes 4 lessons in total.

Why Overload Arithmetic Operators?

Operator overloading lets your own types use familiar symbols like +, -, and *. For value-like types such as vectors, money, or complex numbers, this makes code read like math instead of method calls.

The operator + Syntax

An overloaded operator is declared as a public static method whose name is operator followed by the symbol. At least one parameter must be the containing type.

using System;

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

    public static Vector2 operator +(Vector2 a, Vector2 b)
        => new Vector2(a.X + b.X, a.Y + b.Y);

    public override string ToString() => "(" + X + ", " + Y + ")";
}

public class Program
{
    public static void Main()
    {
        var sum = new Vector2(1, 2) + new Vector2(3, 4);
        Console.WriteLine(sum);
    }
}

Subtraction and Multiplication

You can overload several operators on the same type. Here we add subtraction and scalar multiplication to our vector.

using System;

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

    public static Vector2 operator -(Vector2 a, Vector2 b)
        => new Vector2(a.X - b.X, a.Y - b.Y);
    public static Vector2 operator *(Vector2 a, int k)
        => new Vector2(a.X * k, a.Y * k);

    public override string ToString() => "(" + X + ", " + Y + ")";
}

public class Program
{
    public static void Main()
    {
        var v = new Vector2(5, 6) - new Vector2(2, 1);
        Console.WriteLine(v);
        Console.WriteLine(new Vector2(2, 3) * 4);
    }
}

Operators Are Always static

Overloaded operators must be static. They do not act on a hidden this; instead the operands are passed as explicit parameters. The compiler maps the symbol to the method.

using System;

public struct Money
{
    public decimal Amount;
    public Money(decimal amount) { Amount = amount; }

    public static Money operator +(Money a, Money b)
        => new Money(a.Amount + b.Amount);

    public override string ToString() => "$" + Amount;
}

public class Program
{
    public static void Main()
    {
        var total = new Money(10.5m) + new Money(4.25m);
        Console.WriteLine(total);
    }
}

Unary Operators

Unary operators such as negation take a single operand. Overload operator - with one parameter to support expressions like -v.

using System;

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

    public static Vector2 operator -(Vector2 a)
        => new Vector2(-a.X, -a.Y);

    public override string ToString() => "(" + X + ", " + Y + ")";
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(-new Vector2(3, -7));
    }
}

Mixed-Type Operands

One operand can be a different type. Providing both orders lets users write the expression naturally either way.

using System;

public struct Temperature
{
    public double Celsius;
    public Temperature(double c) { Celsius = c; }

    public static Temperature operator +(Temperature t, double delta)
        => new Temperature(t.Celsius + delta);
    public static Temperature operator +(double delta, Temperature t)
        => new Temperature(t.Celsius + delta);

    public override string ToString() => Celsius + "C";
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Temperature(20) + 5);
        Console.WriteLine(5 + new Temperature(20));
    }
}

Returning New Values

Arithmetic operators should not mutate their operands. They compute and return a new value, keeping the originals unchanged, just like int does.

using System;

public struct Vector2
{
    public int X, Y;
    public Vector2(int x, int y) { X = x; Y = y; }
    public static Vector2 operator +(Vector2 a, Vector2 b)
        => new Vector2(a.X + b.X, a.Y + b.Y);
    public override string ToString() => "(" + X + ", " + Y + ")";
}

public class Program
{
    public static void Main()
    {
        var a = new Vector2(1, 1);
        var b = new Vector2(2, 2);
        var c = a + b;
        Console.WriteLine("a unchanged: " + a);
        Console.WriteLine("result: " + c);
    }
}

Chaining Arithmetic

Because each operator returns the same type, expressions chain naturally and respect normal precedence and associativity.

using System;

public struct Vector2
{
    public int X, Y;
    public Vector2(int x, int y) { X = x; Y = y; }
    public static Vector2 operator +(Vector2 a, Vector2 b) => new Vector2(a.X + b.X, a.Y + b.Y);
    public static Vector2 operator *(Vector2 a, int k) => new Vector2(a.X * k, a.Y * k);
    public override string ToString() => "(" + X + ", " + Y + ")";
}

public class Program
{
    public static void Main()
    {
        var result = new Vector2(1, 1) + new Vector2(2, 2) * 3;
        Console.WriteLine(result);
    }
}

Operators on Classes

Operator overloading works on classes too, not just structs. Be mindful of null: a class operand could be null, so guard if needed.

using System;

public class Complex
{
    public double Re, Im;
    public Complex(double re, double im) { Re = re; Im = im; }
    public static Complex operator +(Complex a, Complex b)
        => new Complex(a.Re + b.Re, a.Im + b.Im);
    public override string ToString() => Re + " + " + Im + "i";
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Complex(1, 2) + new Complex(3, 4));
    }
}

A Complete Numeric Type

Here is a small fraction type with addition. It shows how overloading turns a domain type into something that behaves like a built-in number.

using System;

public struct Fraction
{
    public int Num, Den;
    public Fraction(int num, int den) { Num = num; Den = den; }

    public static Fraction operator +(Fraction a, Fraction b)
        => new Fraction(a.Num * b.Den + b.Num * a.Den, a.Den * b.Den);

    public override string ToString() => Num + "/" + Den;
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Fraction(1, 2) + new Fraction(1, 3));
    }
}

Try It Yourself

Give a money-like struct addition and scalar multiplication, then build an expression that reads like ordinary arithmetic.

using System;

public struct Money
{
    public decimal Amount;
    public Money(decimal a) { Amount = a; }
    public static Money operator +(Money a, Money b) => new Money(a.Amount + b.Amount);
    public static Money operator *(Money a, int qty) => new Money(a.Amount * qty);
    public override string ToString() => "$" + Amount;
}

public class Program
{
    public static void Main()
    {
        var price = new Money(4.50m);
        var total = price * 3 + new Money(2.00m);
        Console.WriteLine(total);
    }
}

Quick Check

Recall the signature of an overloaded operator.

Recap

Overloading arithmetic operators makes value-like types read like math.

  • Declare them public static with the operator keyword.
  • At least one parameter must be the containing type.
  • Return a new value; never mutate operands.
  • Provide both operand orders for mixed-type arithmetic.
Free to start

Learn C# with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
93
Lessons
346

Frequently Asked Questions

Is the “Overloading Arithmetic Operators” lesson free?

Yes — the full text of “Overloading Arithmetic Operators” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO. The C# Academy course includes 4 lessons in total.

What will I learn in “Overloading Arithmetic Operators”?

Define +, -, * for your own types. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 1 of 4.

How long does the “Overloading Arithmetic Operators” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Overloading Arithmetic Operators
  2. Overloading Comparison Operators
  3. User-Defined Conversions
  4. Operator Overloading Best Practices
← Back to C# Academy