C# 14: Performance-Friendly Increment Operators!
From time to time, custom classes with ++ and -- operators are necessary. The more or less big problem with this has been that it's somewhat... well, wasteful. But C# 14 finally brings an elegant solution!
The Old Problem
Let's imagine we have a Counter class and want to be able to increment it - basically the Hello World of counters:
public class Counter
{
private int value;
public static Counter operator ++(Counter c)
{
return new Counter(c.value + 1); // Oops, yet another new instance...
}
}
Every time we write ++myCounter, a completely new instance is created. For a few calls - no problem. But if we do this in a hot loop, garbage accumulates pretty quickly.
The New Solution: Instance Operators
C# 14 lets you define the operators as instance methods:
public class Counter
{
private int value;
// Ta-da! No 'static', no new object
public void operator ++()
{
value++; // Simply change the existing value
}
public void operator --()
{
value--;
}
}
What's Different?
The new instance operators have a few clear rules:
public- must be public (logical)- No
static- they are instance methods after all voidreturn type - return nothing, only modify the instance- No parameters - not even ones with default values
Why Is This So Cool?
In variation of Steve Ballmer: "Performance, Performance, Performance!"
Before:
for (int i = 0; i < 1000000; i++)
{
++myCounter; // 1 million new Counter objects...
}
Now:
for (int i = 0; i < 1000000; i++)
{
++myCounter; // Always the same object, only the value changes
}
Especially for value-like types such as coordinates, counters, or mathematical objects, this is a game-changer!
A Practical Example
Here's a Point type that can finally be incremented efficiently:
public class Point
{
public int X { get; private set; }
public int Y { get; private set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
public void operator ++()
{
X++;
Y++;
}
public void operator --()
{
X--;
Y--;
}
}
// Usage:
var point = new Point(1, 1);
++point; // point is now (2, 2)
++point; // point is now (3, 3)
Thread-Safety Warning ⚠️
Important note: Instance operators modify the state of the object! This means we need to be careful with multi-threading:
// Potential race condition:
Parallel.For(0, 1000, i => ++sharedCounter);
// Better with locking:
public void operator ++()
{
lock (lockObject)
{
value++;
}
}
Happy Coding! 💻