C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
63: Operator Overloading in C#
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
ComplexNumberwith two double properties:RealandImaginary. - 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()andGetHashCode()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.
There are no comments for now.