C# operator overloading, where is my +=?

Coming from a C++ background, I never understood why they left out operator overloading in Java. Sure it can lead to obscure code in the hands of incompetent programmers, but I guess the same goes with cars and incompetent drivers. That can (and does) cause some problems, but I’ve never heard of people proposing to ban all cars so that this relatively small group doesn’t cause any harm any more.

Today I don’t want to solve the problem of incompetent programmers. Today I just want to complain about not being able to overload the += operator in C#. Why is this a problem? As you all know all C# overloading operators need to be defined as public and static. So if you add 2 objects, for example 2 Pixel objects in my GIMP# code, you have to allocate a new Pixel, do your math, and return this new object. This is all done by overloading the + operator: public static operator + (Pixel p1, Pixel p2).

So far, so good. Now in C++ I would add a non-static operator += that simply adds the Pixel parameter to the current instance of my Pixel object. No need to allocate a new Pixel, since I already have it (the implicit this object). In C# I get the += operator “for free”. The downside obviously is that this so-called free method still allocates a new Pixel object before assigning it to my current object 😦 This wouldn’t be so bad if the language would allow me to overload the += operator but this is not possible. Only alternative I have at the moment is to define a Pixel.Add(Pixel p) method, but what’s the point of operator overloading in that case.

Ah well, maybe this shortcoming will be fixed in a future version. I hope someone can tell me what the rationale was behind this design decision.

‘a += b’ is per definition ‘a = a + b’, and C# handles it as such. Allowing for a developer to overload the meaning of the ‘+=’-operator to be something else is a bad idea.

While I understand your ‘problem’ regarding the creation of an extra object and while I see you are not actively trying to redefine what ‘+=’ means, you can easily fix this (as you stated) by adding a new method, a solution that is IMHO better as it does not cloud the original meaning of ‘+=’).

What exactly do you mean with incompetent programmers? Those that don’t use overloading in a “logical” way? Those that don’t document the new workings of the operators they overload?

In my opinion, operator overloading should only be used in very few cases. Operators have meanings that everyone knows once they know the language, if one starts changing them it’s just not natural to know what the operators do anymore.

There are cases when it’s kind of logical to know what overloaded operators do, but it’s not possible to do so in a way that’s clear to everyone. In your case, for instance, does the + sum each color component of the two pixels? From a pragmatic point of view it’s just not certain.

Anyway, I suspect the reason that += and + were defined using the same operator overloading is that most “objects” you would want to have a + or += defined should be valuetype objects. In which case the GC doesn’t apply to any performance problems.

For example,
Number objects
Date objects (TimeSpan)
Matrix objects

Adding a Pixel to another Pixel just doesn’t make sense. Addition should only be provided on an object if there is a corresponding technique in everyday non-computation or mathematical life.

Thanks for all the feedback so far. I guess I wasn’t very clear with my Pixel example. It’s my intention indeed to be able to take for example the average of 2 pixel values (the colors), simple by stating “Pixel average = (pixel1 + pixel2) / 2”. The semantics of this operation might not always be clear because a Pixel object also has a (x, y) coordinate. “average.Color = (pixel1.Color + pixel2.Color) / 2” might be better to state very clearly that we add colors, not coordinates.

I also need to be careful with using words like `incompetent’. The point I was trying to make is that taking away language features is imho not the right approach to prevent unreadable or even incorrect programs. And like a few people here already have stated: operator overloading should be used with care.

@RichB: i’ve too always hated to use += to connect handlers. But “they” always say “it’s the C# way”, not necessarily the most logical way.

@maurits: the way i see it, there still remain some problems with your example. In “(pixel1.Color + pixel2.Color) / 2”, the sum would result in a Color, which would then be divided by 2. What does it mean to divide a color by 2? Also, the temporary sum in parentheses would result in a Color that’s not really a valid Color. For the whole operation to work, the sum must be able to produce a Color that overflows the valid range of Color, so it can be divided by 2 afterwards. IMHO these are problems that are well solved by a simple static Color.Average method, without operator overloading.

@noup: the overflow part is quite easy to take care of and I am not too worried about that. In the end this construct is used to make it easier for developers to write new plug-ins for GIMP. Therefor the operator overloading of the Pixel class should make sense. This discussion helps me in forming an opinion about that. Of course I can add an Average method, but what if I want to take the average of more than 2 pixels? Then I would have to add params in the function declaration. And now I also want to have a weighed average, or for that matter any matrix operation on a certain set of pixels. For me having overloaded operators makes this kind of code very intuitive. But then again, I might be biased. When you look at GIMP code pixels get manipulated all the time by adding them, multiplying them with weighing factors, etc. etc. It’s not as if we are adding 2 objects of type Employee. The main advantage that I see with providing Add, Substract, Multiply, etc. methods is that performance could be better.

@maurits, let me say that i totally understand that overloading in your case may make a lot of sense and really ease development. The only thing is that it’s hard (if not impossible) to have a notion of general intuition. Your opinion is biased, but that’s not necessarily a wrong thing, it’s just that you’re applying the use of overloading to this specific domain.

The overflow part is naturally easy to solve, though the point was to show that overloading drags with it side-effects that may not be visible at first sight. As for the Average method, it doesn’t really matter much, but i think you could use a method with an “infinite” number of args. Still, the use of the expression “X + Y + Z / 3” is definately ok and very understandable, just the X, Y and Zs are what need more attention in the expression, if they are to be understood.

@nazgul: like you already say, it would give a different meaning to the + operator. If I would try a `pixel3 = pixel1 + pixel2′ then pixel1 would be changed. That’s certainly not what a user would expect.

@maurits: If you tried pixel3 = pixel1 + pixel2, pixel1 would not be changed, as the declaration of the method doesn’t contain a reference object for the Pixel in the p1 slot. If it were:

public static Pixel operator + (Pixel &p1, Pixel p2)

Then yes, it would change the value of pixel1. As it stands, however, it does not.

Additionally, I also disagree with being unable to overload many of the operators in C#. I, too, come from a C++ background. I would love to be able to overload [] or +=/-=, etc. in order to do things that seem logical to me, and that I document. The main thing being in large programs where there are many calculations going on at once, you run the risk of having a lot of bloat because of the number of additional objects set aside when making a += call that creates an intermediary value.

@redstatori, as a C++ programmer now learning C# I make the same mistakes I suspect you have just made:

If you tried pixel3 = pixel1 + pixel2, pixel1 would not be changed, as the declaration of the method doesn’t contain a reference object for the Pixel in the p1 slot. If it were:
public static Pixel operator + (Pixel &p1, Pixel p2)
Then yes, it would change the value of pixel1.

The objects in C# are always reference types – there are no concrete/stack objects as in C++.

do you really think it will prevent the guy from doing such things when he calls the method T.Add() instead? (BTW: this case remembers myself of the good old ‘const’ keyword, but that’s a different discussion)

2. Sometimes the meaning of an ‘abused’ operator gets absolutely clear if you know what a class stands for… Don’t tell me that your first thought was “Oh my God they want me to shift left the standard output by a string?!” or “Where is this going to be in memory?” when you saw the << operator of std::cout or the * operator of the std::vector::iterator the very first time.

3. And then you sometimes just HAVE TO inject different code because it’s somehow the aim of the project! I worked on a project which was supposed to enable dozens of engineers (non-computer-scientists) to use BLAS-methods on the GPU in their code without them having to care neither about BLAS nor coping with the GPU but just write their C++ code and focus on their essential work. They had use cases where matrixA = matrixA + matrixB couldn’t have worked because of memory issues but matrixA += matrixB perfectly did. And replacing the operators by full method names would have made their code way less readable.

Ah, people talking about developers as if latter were completely stupid little kids just drive me crazy! There will never be a really perfect programming language available as long as there are still some guys pretending it would be better to disable some language features just to ‘protect the developers from themselves’.

If you think that it is not elegant to use ‘const’, that it is not that good idea to overload operators or think multiple inheritance is evil: JUST DON’T USE THEM, but do not force other people to work as twice as much as they would have to and write messy and bloated code just because there are some handy language features missing!!!!!!

…(Sorry, but I read similar discussions way to often to stay calm at this point.!)