3

This question comes from a previous discussion on C++ Functors (Do functors have an equivalent in C#?).

Why doesn't C# allow overloading operator()?

You can overload operators but what advantage would there be if operator() could also be overloaded?

Community
  • 1
  • 1
4thSpace
  • 43,672
  • 97
  • 296
  • 475
  • 4
    Very few. Lambdas and delegates make it almost pointless. – Richard J. Ross III Jun 16 '13 at 19:58
  • You would blur the line between functions and objects (which delegates already do) and befuddle corporate drone programmers, leading to a disaster of Biblical proportions (Fire and brimstone coming down from the sky! Rivers and seas boiling! Forty years of darkness! Earthquakes, volcanoes! The dead rising from the grave! Human sacrifice! Dogs and cats, living together! Mass hysteria!) I think we can all agree it's better to avoid that. – Ben Voigt Jun 16 '13 at 20:01
  • 1
    BTW, in C#, `operator()` is spelled `Invoke`. – Ben Voigt Jun 16 '13 at 20:03
  • 1
    In C++, Functors give the effect of a function with state. In C# a lambda can do the same thing, as can a delegate, so there's not that much to be gained from adding operator() to C#, other than some mild syntactic sugar. – Matthew Watson Jun 16 '13 at 20:06
  • About the syntactic sugar part, I gotta admit, sometimes writing e.g. `Some(2)` in Scala makes me feel fuzzy inside that you can override the `apply` method (which is the `()` 'operator'). – Patryk Ćwiek Jun 16 '13 at 20:07
  • @BenVoigt: Nice point. Can you post as answer with a little explanation? Matthew: Not to get off track but C++ also has lambdas...but still has Functor. – 4thSpace Jun 16 '13 at 20:31
  • C++ has functors for long time and lambdas are recent addition to the language. – Jagannath Jun 17 '13 at 02:54
  • C++ lambdas are just a shorthand way of defining functors... but C# is parallel to this, lambdas are just shorthand for defining anonymous delegates (except when used with expression trees). Expression trees are possible in C++ without special language support. – Ben Voigt Jun 17 '13 at 13:22
  • Why ask if a language doesn't overload an operator (implying that it should have done so) if you don't even know why it should be overloaded? – Servy Jun 17 '13 at 14:08

1 Answers1

2

C# has operator(), which it spells Invoke.

Anytime you define a delegate type, you are defining a class with a method named Invoke and can use function call syntax with instances of that class, which will result in a call to Invoke. Like operator(), C# delegate Invoke methods can have almost any function signature.

Unlike C++ operator(), C# doesn't allow defining arbitrary other members on the same class that defines Invoke. You could say that C# is enforcing the Single Responsibility Principle here. This isn't a major limitation, however, because C# delegates get wired to another object that provides storage of state for the function object.

A more severe (in the sense that there is no simple workaround) limitation on C# Invoke compared to C++ operator() is that C# delegate Invoke methods cannot be overloaded nor polymorphic. This is a consequence of the need to forward the call to a method on another object, but it prevents some usage scenarios possible with C++ custom functors.

It would be interesting to see what happens if you defined an overloaded Invoke method using MSIL. Certainly you would confuse the C# compiler if you tried to use such a delegate class, and probably also the CLR runtime. So this is a curiosium rather than a practical approach.

C++ std::function is quite similar to C# delegate types in capability and limitations. It also forwards invocations, and isn't polymorphic on the call signature. Ditto for C++11 lambdas, although C++14 lambdas will allow templated operator() and call-site type polymorphism (unlike C# lambdas which allow only point-of-definition polymorphism).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • I'd be curious what would happen if a `Delegate`-derived type were defined with multiple `Invoke` methods. Certainly things like `Delegate.Combine` would be totally bamboozled, but I wonder whether the `Invoke` itself would work. I really wish that instead of the static `Delegate.Combine` and `Delegate.Remove`, the delegate types had defined their own joining methods. Such joining methods could then either chain to `Delegate.Combine` or do something else, as appropriate. – supercat Jul 25 '13 at 15:58