views:

676

answers:

5

What scenarios would you consider operator overloading in .net?

+10  A: 
  • I would strongly consider overloading == and != anywhere I override Equals
  • I would consider (much less strongly) overloading comparison operators anywhere I implement IComparable<T>
  • I would consider overloading arithmetic operators for fundamentally numeric types
  • I would consider providing explicit conversions for "wrapper" types (like Nullable<T>)
  • I would very rarely consider providing implicit conversions

The golden rule is not to overload operators if the meaning isn't entirely obvious. For example, I think it would be pretty odd to have a + operator on Stream - it could mean "make a writable T here, so that writes to the result write to both" or it could mean "read one after the other" or probably other things.

In my experience it's pretty rare to overload anything other than == and !=.

Jon Skeet
I'm not sold on overriding `==` when you override `.Equals`. Maybe it's the Java background (though I suppose you have that too). Just personal preference I suppose.
Noon Silk
I don't like if == and != do not reference comparison for reference types.
Stefan Steinegger
stefan: agreed.
Noon Silk
@silky/Stefan: Why not? Silky's already given string as an exception in another comment - but why? If two objects have value equality, why would you not want them to be easier to compare for that equality by using ==? There are some cases where it's important to make both reference and value equality easily distinguishable, but I think it's at least worth strongly *considering* it otherwise...
Jon Skeet
I guess the reason why is that you may implement `.Equals` for some purpose; perhaps matching in a Dictionary when two fields are equal. Though in this case, you still may not want `==` to return true, just incase you feel like comparing the actual references. In string perhaps the difference is immutability (and the simple structure of it; effectively just one thing). In a class with more things, it is nice to have the fallback comparision of `==`. Consider, definitely. But not 'strongly'.
Noon Silk
@silky: Don't you think it could be confusing to someone using your code that Equals and == don't have the same behavior? I would expect that they have the same result...
Meta-Knight
Meta-Knight: It wouldn't confuse me personally, and I would expect with anyone else, I could trivially explain my reasons for any given implementation method I selected. For a complete newbie trying to read it? Sure, but that's because they're new, not specifically due to the implementation.
Noon Silk
I'd say that if you're implementing equality for just a single purpose rather than general purpose equality, you should be implementing IEqualityComparer in a separate (possibly nested) class instead. And your exception for string due to immutable doesn't take account of the fact that you can create your own immutable classes too. In fact, I'd rarely override Equals for mutable classes...
Jon Skeet
I take your point about `IEqualityComparer`; but probably that would not be my approach, to my mind it is reasonable to override `.Equals` for that purpose. Though I will admit that I can't think of a time that I've actually done it, in c# (at least in the last 5 years, memory is not that good).
Noon Silk
@silky: I think I may have misunderstood your dictionary point. I agree it's fine to override Equals if you're providing *general* equality. I thought you were talking about "for this map, I need equality on just these two fields... so I'll override Equals in that way".
Jon Skeet
+1  A: 

I did request to close this, but perhaps it can remain open (I tried to change my mind but apparently you can't revoke a close request :P)

I will answer personally: never.

I never think it's a good idea to implement operator overloading. There is only one exception: If I'm writing some sort of collection (it doesn't happen very often) and I want to implement the indexers [].

In my personal opinion, I do not think it is ever appropriate to be overriding ==, and other such things. But then again, I do not work in complex fields of maths and finance, where such things may be useful. But I can't speak from experience in that matter (actually, I can in the finance world, and we didn't do it there).

Noon Silk
yeah it's annoying you can't revoke close.
RichardOD
So do you think it's a pity that (say) string overloads ==? I know I don't...
Jon Skeet
`string` is an exception, for sure, but also they will be reference equal, if interned, so it arguably makes sense.
Noon Silk
Most strings I work with aren't interned...
Jon Skeet
Regardless, it's a concession I'm more than comfortable with; in Java it was the one annoyance that you had to compare strings in that fashion; and I'm sure purists would look down their noses at me for quite enjoying it now. In my mind, it is an exception, and one I'm happy with.
Noon Silk
And working with DateTime/TimeSpan? How about Decimal (which isn't a BCL primitive type)?
Jon Skeet
Yes, `DateTime` again is another great exception. I don't know what answer you're looking for from me. I am quite happy for the language designers to overload operators (I've even come to like += on events) I'm not comfortable with regular-joe programmers doing it in every day applications.
Noon Silk
That just means you need to be careful with it... like many other features. Note that it's the BCL designers who have done it, not the language designers (other than for string concatenation). I'm not comfortable with any "never" so emphatically stated that would prevent a well-designed class library from having similar usability to the BCL. Suppose someone were to port Joda Time to .NET - would it not make sense for them to use operator overloading similarly? Likewise how can it "never" be good idea to implement operator overloading if you are happy for the BCL to do it?
Jon Skeet
Jon: One thing I learned form the Java team is that features I need to be 'careful' with, are ones I'd rather not have, for maintainability. I think there is a nice balance, but Java handled it better, IMHO. Further, I think you understand my general sentiment, which is: Newbies, don't do it, Experts: Probably don't do it, unless you can really justify why. Language authors: It's your show, do what you like :)
Noon Silk
@Silky- I would update your answer to be "almost never". You've kind of agreed in the comments that never is incorrect. :-). It's good to point out that going mad with operator overloading is a lot worse than not doing it at all.
RichardOD
RichardOD: I won't update it, because I'm speaking *directly* from personal experience: I have never needed to do it. IMHO, the obvious answer is "almost never"; I think more useful is to show that it's never come up for me at all.
Noon Silk
you cannot override the = that is the assignment operator. Surely you mean the comparison operator ==
MaLio
@Silky- fair enough. However the question says "would you"- your answer is in effect answering "have you". After some reflection I decided to +1 as I think the answer gets people thinking about whether it is really appropriate.
RichardOD
+1  A: 

I would consider using operator overloading for arithmetic operations on types that represent a logical value. For instance, there have been occasions when I wished that Point had an overload for the + and - operators.

Fredrik Mörk
+2  A: 

I consider overriding operators i this cases:

  • == and != when it is a simple value type, and implement value comparison. In other types, I expect that == and != so reference comparison and are also not expensive.
  • comparison operators (>, >= etc) in the same case as above if it is just a numeric value.
  • I actually never overload aritmetic operators, but would do this for the same kind of numeric values if it would enhance the usability.
  • casting operators if the type can be lossless turned to an appropriate other type.
Stefan Steinegger
I actually just overloaded >, >=, <, <= for strings. I'm comparing permissions for MembershipUser objects to determine if they are in a role that is equal, above, or below the mandatory level to perform some action. Essentially its creating hierarchical Permissions. Is my approach inadvisable?
splatto
MemebershipUser does not sound like a numeric value. I think that comparison operators are too implicit, you might not understand what they mean when reading the code. A method called `HasSufficientPermission` or `IsSameOrHigherLevel` or whatever is self documenting. On the other hand, when your class is called `PermissionLevel` or the like, it is quite clear what it means when a PermissionLevel is greater then the other. But all the same, explicit methods are much easier to understand and you don't loose anything.
Stefan Steinegger
+8  A: 

I think the Framework design guidelines provide some decent advice:

  • AVOID defining operator overloads, except in types that should feel like primitive (built-in) types.
  • CONSIDER defining operator overloads in a type that should feel like a primitive type.
  • DO define operator overloads in structs that represent numbers (such as System.Decimal).
  • DO NOT be cute when defining operator overloads.
  • DO NOT provide operator overloads unless at least one of the operands is of the type defining the overload.
  • DO overload operators in a symmetric fashion.
  • CONSIDER providing methods with friendly names that correspond to each overloaded operator.
RichardOD
Nice. I'm glad that I'm actually not so far from this :-)
Stefan Steinegger
Yeap- it is good when your own views align to the views of the Framework design guidelines book- it really is good.
RichardOD