views:

141

answers:

9

I'm curious about how some operators work (+, -) in terms of objects.

I've always wondered how EventHandlers work by adding a method:

Foo.Action += new FooActionHandler

If not an Event, what about returning a comparison?

DateTime - DateTime

That returns a TimeSpan object, and I'm a bit baffled as to how that's possible. I use these kinds of methods all the time but I've never understood the inner workings of them. How would I create my own class to do something like this?

+3  A: 

You can define operators like this:

public static MyClass operator +(MyClass a, MyClass b) { }

With the same syntax for -, *, etc.

Here are some tips (my opinion, mostly):

  • Don't put the actual logic in the operator - create a static method.
    // NOT
    public static MyClass operator +(MyClass a, MyClass b) { /* ... */ }
    // YES
    public static MyClass Add(MyClass a, MyClass b) { return new MyClass(a.Prop + b.Prop); }
    public static MyClass operator +(MyClass a, MyClass b) { return Add(a, b); }
  • Don't bend the operators to do something they shouldn't - ie, don't use + to add to a list, or - to remove from a list, for example. This causes two problems:
    1. It isn't very well-regarded in the community
    2. The compiler won't catch errors if you accidentally add two objects.
Lucas Jones
Shouldn't the Add method be returning a MyClass and not the added Prop values?
Rorschach
Yes. Damn my weak, contrived examples!
Lucas Jones
There - still quite weak, but possibly compileable.
Lucas Jones
+1  A: 

This is called operator overloading. Google will return many articles that explain how it works, and when to use and not use it.

http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=88

Matthew Vines
+10  A: 

You can overload operators to perform whatever action you want. Here is some good documentation for how to do it in C#.

The gist of it is that you provide a context for the operator (your class) and what occurs with the parameters to it. A sample might look like this:

   // Overload '+' for my class
   public static MyClass operator +(MyClass c1, MyClass c2) 
   {
      MyClass newMyClass = new MyClass();
      newMyClass.MyIntProperty = c1.MyIntProperty + c2.MyIntProperty;
      return newMyClass;
   }
womp
That makes sense and would explain a lot of what I see in code. Much easier than I Thought it would be, as well.
Corey
A: 

It is called operator overloading. C# allows you to overload select operators.

There is more information on this here.aspx).

Matthew Manela
A: 

You can overload an operator to do whatever you want.

Lets say I have a Truck Class, and MachineGun class, I want to be able to do this:

Transformer myTransformer = mytruck + myGun;

Neil N
Sadly ( myTruck + myGun ).GetType() == typeof(ScrapMetal) != typeof(Transformer). Don't try this at home, kids.
stevemegson
Transformers aren't usually trucks; typically they vary from cars to airplanes. I think it would be best to use a myVehicle class instead.
Corey
A: 

the += and -= for EventHandlers are shortcuts for Delegate.Combine and Delegate.Remove, this is accomplished with operator overloading, see this site for more details.

Brandon
A: 

This is known as operator overloading. It's used by the framework extensively, however you should avoid doing it since it can lead to some bad code if you don't know what you're doing.

Most programmers don't expect to see a custom class with operators being overloaded so it can become maintenance hell when other programmers have to look at your code and figure out what is going on.

Of course, there are situations where you may find it useful, but usually you're better off just using methods instead of creating operator overloads. You can find out more info from Microsoft here:

http://msdn.microsoft.com/en-us/library/aa288467.aspx

Dan Herbert
A: 

Plenty of answers have covered how you do it. Now just remember that you'll almost never want to actually do it yourself. You need to be really sure that anyone using your class will agree with you about what subtracting two MyClass objects means. If it represents some kind of mathematical structure (vector, matrix, etc) then you're probably safe. Otherwise, it's probably unclear. Notice that Microsoft defined subtraction for DateTime, but didn't allow

List<string> myList = new List<string>();
myList += "foo";

Any time you write

static Foo operator -( Foo a, Foo b )

then think about what you'd call that method if you couldn't override subtraction. If the best possible name isn't Subtract, then you probably want to just create a method with that other name.

stevemegson