It's dangerous to code alone! Take this.

Generic Math Part 1: The Problem

Published on 17 Oct 2022.

This is Part 1 in a series about generic math. You can view all parts here: Part 1 Part 2 Part 3 Part 4

C# 11 and .NET 7 added a feature known as generic math. It is a feature that demands knowing a fair bit about interfaces, generics, and operator overloading to truly understand. The somewhat limited places where it is useful, along with the fact that it combines a bunch of rather advanced and complicated features made me opt to leaving any sort of detailed discussion around it out of the book. However, I didn’t want it to go completely unaddressed, so I’ve chosen to make a series of blog posts about it instead!

Here, in Part 1, we’re going to discuss the kind of problem that generic math can help solve. This will be a running problem that we will work through in this series.

Consider this method:

public static float Add(float a, float b, float c)
{
    return a + b + c;
}

This code is really quite simple–too simple, in fact. If this is really what you’re doing, I’d generally not suggest making a whole method for a three-way add, but just do a + b + c in the places where you need it.

But you can think of this as a placeholder. This is a very simple math-related algorithm, but the aren’t always so simple. For example, you could have an array or list that you want to add up. Or a 2D array that you want to sum up. Or maybe you want to compute an average (which requires summing everything and dividing by the number of items). Or maybe you want to compute the median value, which requires sorting and picking the middle item. Or maybe you have a giant graph structure with data elements that you want to average.

The point is, it could be way more complicated than this. I’m intentionally keeping it simple for the sake of understanding, since what we’re doing here is already going to be very complicated, as we’ll soon see.

Anyway…

That Add method to add three float values is simple enough, but what if we also want to be able to add double values or int values? What if we want to add three instances of a more complicated type, like a Point or Vector class?

The poor man’s version would be to just duplicate this code and swap out all of the occurrences of float for these other types:

public static float Add(float a, float b, float c)
{
    return a + b + c;
}

public static double Add(double a, double b, double c)
{
    return a + b + c;
}

public static int Add(int a, int b, int c)
{
    return a + b + c;
}

public static Point Add(Point a, Point b, Point c)
{
    return a + b + c;
}

And for reference going forward, let’s suppose this is our Point class definition:

public class Point
{
    public float X { get; }
    public float Y { get; }
    public Point(float x, float y) { X = x; Y = y; }
    public static Point operator +(Point a, Point b) =>
                           new Point(a.X + b.Y, a.Y + b.Y);
}

If you go back and look at those different definitions of Add, you’ll see that they’re all exactly identical except the types in use. That should be a very strong signal that we could use generics to reduce the duplication.

Alas, this code has a big problem: that + operator is going to complicate things. We’ll sort through that in the upcoming posts by using the new features in C# 11. But this was not really solvable before this version.

This is Part 1 in a series about generic math. You can view all parts here: Part 1 Part 2 Part 3 Part 4