Operator overloading, when to
-
I have written a few classes to handle geometry primitives, like Length, Angle, etc, to make sure there are no unit mismatches as could happen if the values are stored in plain double types. Coming from C++, I overloaded operator== et al, to compare the actual values, which to me would be intuitive. However, co-workers coming from Java claimed operator== should be reserved for comparing references, and that I should use Equal() and the like for comparison. The C#-ers here seems to be divided. Is there a design guide for operator overloading in C#? How would you prefer the implementation? Operator overloading or plain old function calls?
-
I have written a few classes to handle geometry primitives, like Length, Angle, etc, to make sure there are no unit mismatches as could happen if the values are stored in plain double types. Coming from C++, I overloaded operator== et al, to compare the actual values, which to me would be intuitive. However, co-workers coming from Java claimed operator== should be reserved for comparing references, and that I should use Equal() and the like for comparison. The C#-ers here seems to be divided. Is there a design guide for operator overloading in C#? How would you prefer the implementation? Operator overloading or plain old function calls?
I think there is not a clear rule for this. If you overload the other relational operators (<, > <=, >=) then I think that overloading == for bit equality makes sense. Rememeber you can always use the static method Object.ReferenceEquals to compare references.
-
I have written a few classes to handle geometry primitives, like Length, Angle, etc, to make sure there are no unit mismatches as could happen if the values are stored in plain double types. Coming from C++, I overloaded operator== et al, to compare the actual values, which to me would be intuitive. However, co-workers coming from Java claimed operator== should be reserved for comparing references, and that I should use Equal() and the like for comparison. The C#-ers here seems to be divided. Is there a design guide for operator overloading in C#? How would you prefer the implementation? Operator overloading or plain old function calls?
You could always use Object.ReferenceEquals.. But, in my opinion, types like Length and Angle etc should be value types (and therefore structs, unlike in C++, in C# classes can never be value types) - they represent a value instead of a thing and in almost every situation will it be more intuitive if they also behave like values. To counter his argument: 1) C# is not Java 2) operator== on strings compares for value-equality (even when you make sure that string-interning is avoided)
-
I have written a few classes to handle geometry primitives, like Length, Angle, etc, to make sure there are no unit mismatches as could happen if the values are stored in plain double types. Coming from C++, I overloaded operator== et al, to compare the actual values, which to me would be intuitive. However, co-workers coming from Java claimed operator== should be reserved for comparing references, and that I should use Equal() and the like for comparison. The C#-ers here seems to be divided. Is there a design guide for operator overloading in C#? How would you prefer the implementation? Operator overloading or plain old function calls?
As long as it is clear in the documentation for your class that == does value equality checking, and that makes sense for how the class would normally be used, it is fine to do that in .Net. As mentioned below, string.== does that. However, I also agree with the comment below that simple wrappers like that should be value types (structs). Edit: Below=above. I forgot which way CP forums stack posts.
-
I have written a few classes to handle geometry primitives, like Length, Angle, etc, to make sure there are no unit mismatches as could happen if the values are stored in plain double types. Coming from C++, I overloaded operator== et al, to compare the actual values, which to me would be intuitive. However, co-workers coming from Java claimed operator== should be reserved for comparing references, and that I should use Equal() and the like for comparison. The C#-ers here seems to be divided. Is there a design guide for operator overloading in C#? How would you prefer the implementation? Operator overloading or plain old function calls?
Niklas Lindquist wrote:
co-workers coming from Java claimed operator== should be reserved for comparing references
That's because Java got it wrong and they want to share the misery. Use
==
for value equality in .net; it's right way, the intuitive way. -
I have written a few classes to handle geometry primitives, like Length, Angle, etc, to make sure there are no unit mismatches as could happen if the values are stored in plain double types. Coming from C++, I overloaded operator== et al, to compare the actual values, which to me would be intuitive. However, co-workers coming from Java claimed operator== should be reserved for comparing references, and that I should use Equal() and the like for comparison. The C#-ers here seems to be divided. Is there a design guide for operator overloading in C#? How would you prefer the implementation? Operator overloading or plain old function calls?
Niklas Lindquist wrote:
Coming from C++, I overloaded operator== et al, to compare the actual values
I am taking that to mean that you are overloading others besides equality. Coming from C++ I almost never used operator overloading. At two C++ shops it was specifically forbidden to use it. Excluding the comments about equality there can be specific circumstances where operators (all of them) might be appropriate to use. Numeric representation are example of this. Thus Length might be a suitable candidate. Angle on the other hand is less clear. But possible. But hypothetically does a "geometry primitives" include a circle, square and rectangle? If so please explain, objectively, how one implements less than for a square. And how one represents it for a square and rectangle. And a square and circle. And once you have that if someone else can come up with a different interpretation then - don't use operator overloading because the operation is not in fact clear and well defined. As an example of this what does less than mean for an Angle? Seems obvious that 60 degrees is less than 90 degrees. However is 60 degrees less than 300 degrees? And if you think that is obvious then draw a 60 degree angle in a circle and explain what the 'angle' measures on both sides of the line.
-
Niklas Lindquist wrote:
co-workers coming from Java claimed operator== should be reserved for comparing references
That's because Java got it wrong and they want to share the misery. Use
==
for value equality in .net; it's right way, the intuitive way.PIEBALDconsult wrote:
That's because Java got it wrong and they want to share the misery.
Having seen some truly hideous usages of operator overloading including at least one that I wrote myself and having never seen any truly inspired usage of the same I would say that Java got it right. So in terms of misery the win goes to C++.
-
Niklas Lindquist wrote:
Coming from C++, I overloaded operator== et al, to compare the actual values
I am taking that to mean that you are overloading others besides equality. Coming from C++ I almost never used operator overloading. At two C++ shops it was specifically forbidden to use it. Excluding the comments about equality there can be specific circumstances where operators (all of them) might be appropriate to use. Numeric representation are example of this. Thus Length might be a suitable candidate. Angle on the other hand is less clear. But possible. But hypothetically does a "geometry primitives" include a circle, square and rectangle? If so please explain, objectively, how one implements less than for a square. And how one represents it for a square and rectangle. And a square and circle. And once you have that if someone else can come up with a different interpretation then - don't use operator overloading because the operation is not in fact clear and well defined. As an example of this what does less than mean for an Angle? Seems obvious that 60 degrees is less than 90 degrees. However is 60 degrees less than 300 degrees? And if you think that is obvious then draw a 60 degree angle in a circle and explain what the 'angle' measures on both sides of the line.
jschell wrote:
But hypothetically does a "geometry primitives" include a circle, square and rectangle?
Not in my problem domain. They all consist of a single
double
value. Maybe physics primitives would have been a better description.jschell wrote:
However is 60 degrees less than 300 degrees?
My angles does not wrap around. 0 and 360 are different values and they might go well beyond a full turn. I think you might confuse this with a normalized angle. But I see your point. If there can be confusion, there probably will. Thanks.
-
PIEBALDconsult wrote:
That's because Java got it wrong and they want to share the misery.
Having seen some truly hideous usages of operator overloading including at least one that I wrote myself and having never seen any truly inspired usage of the same I would say that Java got it right. So in terms of misery the win goes to C++.
jschell wrote:
truly hideous usages of operator overloading
I would say that that describes Java. :-D C and C# are the only languages I consider.
-
PIEBALDconsult wrote:
That's because Java got it wrong and they want to share the misery.
Having seen some truly hideous usages of operator overloading including at least one that I wrote myself and having never seen any truly inspired usage of the same I would say that Java got it right. So in terms of misery the win goes to C++.
You can abuse almost any language feature.. The "no operator overloading" along with the "no structs" (though that one is not as bad) restrictions make it impossible to create proper new numeric types in Java, and that just sucks. It makes the predefined types more magic, and it makes working with any non-predefined numeric type a pain. As for the abuse, sure, you can do that. You can also have overloads Foo(int) and Foo(long) and have them do something completely different - that's on the same level as operator overloading abuse, but Java still allows that. You can also override some method (accidentally even, in Java) and have it completely break the Liskov substitution principle.
-
PIEBALDconsult wrote:
That's because Java got it wrong and they want to share the misery.
Having seen some truly hideous usages of operator overloading including at least one that I wrote myself and having never seen any truly inspired usage of the same I would say that Java got it right. So in terms of misery the win goes to C++.
-
You can abuse almost any language feature.. The "no operator overloading" along with the "no structs" (though that one is not as bad) restrictions make it impossible to create proper new numeric types in Java, and that just sucks. It makes the predefined types more magic, and it makes working with any non-predefined numeric type a pain. As for the abuse, sure, you can do that. You can also have overloads Foo(int) and Foo(long) and have them do something completely different - that's on the same level as operator overloading abuse, but Java still allows that. You can also override some method (accidentally even, in Java) and have it completely break the Liskov substitution principle.
David1987 wrote:
The "no operator overloading" along with the "no structs" (though that one is not as bad) restrictions make it impossible to create proper new numeric types in Java, and that just sucks. It makes the predefined types more magic, and it makes working with any non-predefined numeric type a pain.
Since the vast majority of programming in the world does not involve that it isn't a significant problem. And since most programs that do deal with specialized numerics often have other requirements, such as performance and or significant other functionality (non-numeric) then one should either choose an appropriate language or live with the small amount of code that java entails. The obvious analogy to that is that SQL is very poor candiate for string manipulation and regexes and thus applications used widely, such as editors, should not be written in SQL. That however doesn't mean that SQL suffers because of it.
David1987 wrote:
As for the abuse, sure, you can do that. You can also have overloads Foo(int) and Foo(long) and have them do something completely different - that's on the same level as operator overloading abuse, but Java still allows that. You can also override some method (accidentally even, in Java) and have it completely break the Liskov substitution principle.
No. It is not a question of whether abuse can happen. The point is that it does happen. Enough so that me and others have seen it. And it is not accidental.
-
jschell wrote:
truly hideous usages of operator overloading
I would say that that describes Java. :-D C and C# are the only languages I consider.
PIEBALDconsult wrote:
C and C# are the only languages I consider.
Myself I use languages that are appropriate for the job. Those include C++, C#, Java, SQL (vendor specific implementations), Perl and various OS scripting languages. Myself I wouldn't use C versus C++ unless forced. Small differences in one language do not matter in terms of choice over another.
-
jschell wrote:
Having seen some truly hideous usages of operator overloading
You cannot blame the language if users abuse it. A poor programmer will always be a poor programmer. It's all about design, style and discipline.
Niklas Lindquist wrote:
You cannot blame the language if users abuse it. A poor programmer will always be a poor programmer. It's all about design, style and discipline.
As with many others, here and on the java site (who complain about operator overloading) you either missed or ignored the point. The point is not that it can be misused. The point is that it does get misused. And I have seen no evidence that does not suggest that there are far more examples of misuse than correct usage. As well your view applies equally to pointers and explicit memory management. And certainly I have seen uses of that which are in fact elegant and which cannot be implement by other stategies. Unlike operator overloading. Yet I don't see people insisting that Java/C# should have those.
-
David1987 wrote:
The "no operator overloading" along with the "no structs" (though that one is not as bad) restrictions make it impossible to create proper new numeric types in Java, and that just sucks. It makes the predefined types more magic, and it makes working with any non-predefined numeric type a pain.
Since the vast majority of programming in the world does not involve that it isn't a significant problem. And since most programs that do deal with specialized numerics often have other requirements, such as performance and or significant other functionality (non-numeric) then one should either choose an appropriate language or live with the small amount of code that java entails. The obvious analogy to that is that SQL is very poor candiate for string manipulation and regexes and thus applications used widely, such as editors, should not be written in SQL. That however doesn't mean that SQL suffers because of it.
David1987 wrote:
As for the abuse, sure, you can do that. You can also have overloads Foo(int) and Foo(long) and have them do something completely different - that's on the same level as operator overloading abuse, but Java still allows that. You can also override some method (accidentally even, in Java) and have it completely break the Liskov substitution principle.
No. It is not a question of whether abuse can happen. The point is that it does happen. Enough so that me and others have seen it. And it is not accidental.
-
David1987 wrote:
The "no operator overloading" along with the "no structs" (though that one is not as bad) restrictions make it impossible to create proper new numeric types in Java, and that just sucks. It makes the predefined types more magic, and it makes working with any non-predefined numeric type a pain.
Since the vast majority of programming in the world does not involve that it isn't a significant problem. And since most programs that do deal with specialized numerics often have other requirements, such as performance and or significant other functionality (non-numeric) then one should either choose an appropriate language or live with the small amount of code that java entails. The obvious analogy to that is that SQL is very poor candiate for string manipulation and regexes and thus applications used widely, such as editors, should not be written in SQL. That however doesn't mean that SQL suffers because of it.
David1987 wrote:
As for the abuse, sure, you can do that. You can also have overloads Foo(int) and Foo(long) and have them do something completely different - that's on the same level as operator overloading abuse, but Java still allows that. You can also override some method (accidentally even, in Java) and have it completely break the Liskov substitution principle.
No. It is not a question of whether abuse can happen. The point is that it does happen. Enough so that me and others have seen it. And it is not accidental.
Ok I'm bored so I'm going to argue anyway.
jschell wrote:
Since the vast majority of programming in the world does not involve that it isn't a significant problem.
Not sure what world you're living in. Every time a vector or a int128 (or larger) is needed, Java will make your life a hell by insisting on manual cloning and writing verbose a.Multiply(b) and the like, for no reason other than that operator overloading can and is abused. Frankly it's none of their busyness whether I choose to abuse their language or not. But then again maybe you're working for some boring company just maintaining even more boring applications (as they call them, versus actual programs) - you know, the kind of program that doesn't actually do anything but just glues some stuff together.
jschell wrote:
And it is not accidental.
Of course it isn't. I was referring to overloading methods in Java, which you can do accidentally because it doesn't require any syntax. It also will happen sooner or later and that's a nasty bug which is hard to find.
You can also override some method (accidentally even, in Java) and have it completely break the Liskov substitution principle.
People will do it, on purpose too. So lets ban virtual methods. In fact, let's ban strings and IO and arrays and dictionaries and floating point numbers and abstract classes and definitely reflection, all of which are frequently abused.
-
David1987 wrote:
Congratulations, you are a troll.
I see...so expressing my opinion makes me a troll while you expressing yours is just the thoughtful insight of a recognized genius?
-
Ok I'm bored so I'm going to argue anyway.
jschell wrote:
Since the vast majority of programming in the world does not involve that it isn't a significant problem.
Not sure what world you're living in. Every time a vector or a int128 (or larger) is needed, Java will make your life a hell by insisting on manual cloning and writing verbose a.Multiply(b) and the like, for no reason other than that operator overloading can and is abused. Frankly it's none of their busyness whether I choose to abuse their language or not. But then again maybe you're working for some boring company just maintaining even more boring applications (as they call them, versus actual programs) - you know, the kind of program that doesn't actually do anything but just glues some stuff together.
jschell wrote:
And it is not accidental.
Of course it isn't. I was referring to overloading methods in Java, which you can do accidentally because it doesn't require any syntax. It also will happen sooner or later and that's a nasty bug which is hard to find.
You can also override some method (accidentally even, in Java) and have it completely break the Liskov substitution principle.
People will do it, on purpose too. So lets ban virtual methods. In fact, let's ban strings and IO and arrays and dictionaries and floating point numbers and abstract classes and definitely reflection, all of which are frequently abused.
David1987 wrote:
Not sure what world you're living in. Every time a vector or a int128 (or larger) is needed, Java will make your life a hell by insisting on manual cloning and writing verbose a.Multiply(b) and the like, for no reason other than that operator overloading can and is abused. Frankly it's none of their busyness whether I choose to abuse their language or not.
Presumably you mean 'vector' in terms of mathematics and not in terms of the java class. Based on that, the point is meaningless. In terms of lines of code in the world the code that requires vectors is so small as to be unmeasurable.
David1987 wrote:
But then again maybe you're working for some boring company just maintaining even more boring applications (as they call them, versus actual programs) - you know, the kind of program that doesn't actually do anything but just glues some stuff together
Not sure what that means but most of the applications I write do glue things together. And they also make a lot of money both directly and indirectly. I will admit that getting a regular paycheck and being able to pay bills is in fact 'boring' compared to the alternative. Applications that make money lead to that sort of boredom.
David1987 wrote:
Of course it isn't. I was referring to overloading methods in Java, which you can do accidentally because it doesn't require any syntax. It also will happen sooner or later and that's a nasty bug which is hard to find.
I don't recall it happening to me. I do recall hundreds, thousands, perhaps hundreds of thousands of logic errors of which many are in fact hard to diagnose and sometimes very hard to solve. So I suspect the one of which you speak is lost in the noise.
David1987 wrote:
People will do it, on purpose too. So lets ban virtual methods.
I haven't seen many problems with that in java. I can't recall any. I saw more of that sort of problem in C++ with people not understanding such things as the role of a virtual dtor. And working around the lack of virtual methods can be done but is much harder.
David1987 wrote:
In fact, let's ban strings and IO and arrays and dictionaries and floating point numbers and abstract classes and definitely reflection, all of which are frequently
-
David1987 wrote:
Not sure what world you're living in. Every time a vector or a int128 (or larger) is needed, Java will make your life a hell by insisting on manual cloning and writing verbose a.Multiply(b) and the like, for no reason other than that operator overloading can and is abused. Frankly it's none of their busyness whether I choose to abuse their language or not.
Presumably you mean 'vector' in terms of mathematics and not in terms of the java class. Based on that, the point is meaningless. In terms of lines of code in the world the code that requires vectors is so small as to be unmeasurable.
David1987 wrote:
But then again maybe you're working for some boring company just maintaining even more boring applications (as they call them, versus actual programs) - you know, the kind of program that doesn't actually do anything but just glues some stuff together
Not sure what that means but most of the applications I write do glue things together. And they also make a lot of money both directly and indirectly. I will admit that getting a regular paycheck and being able to pay bills is in fact 'boring' compared to the alternative. Applications that make money lead to that sort of boredom.
David1987 wrote:
Of course it isn't. I was referring to overloading methods in Java, which you can do accidentally because it doesn't require any syntax. It also will happen sooner or later and that's a nasty bug which is hard to find.
I don't recall it happening to me. I do recall hundreds, thousands, perhaps hundreds of thousands of logic errors of which many are in fact hard to diagnose and sometimes very hard to solve. So I suspect the one of which you speak is lost in the noise.
David1987 wrote:
People will do it, on purpose too. So lets ban virtual methods.
I haven't seen many problems with that in java. I can't recall any. I saw more of that sort of problem in C++ with people not understanding such things as the role of a virtual dtor. And working around the lack of virtual methods can be done but is much harder.
David1987 wrote:
In fact, let's ban strings and IO and arrays and dictionaries and floating point numbers and abstract classes and definitely reflection, all of which are frequently
Strings and floats and reflection are very often abused. Enough so that I see such abuses pop up in the C# forum about every few weeks or so. But operator overloading abuse? Never in C#.. sometimes in C++, which sets the wrong example with their << on streams - and still less often than string-abuse. String abuse is especially bad since it causes performance trouble real quick - as does Object abuse, which I hadn't even previously mentioned (some people seem to think that you have to wrap everything in an object).
jschell wrote:
Based on that, the point is meaningless. In terms of lines of code in the world the code that requires vectors is so small as to be unmeasurable.
Sure, you can put everything on one line.. which is a different kind of abuse, also made possible by java, but easily defeatable with auto-formatting. The raytracer we had to write in University became a horror of tangles Subtract's and Multiply's that in no way looked like the actual formula's. It sucked. With operator overloading it wouldn't have been such a pain.
jschell wrote:
Operator overloading is often misused.
Prove it. I've never seen it.