41

I know that the += operator will add a method to the invocation list maintained by the Delegate base object, for example

using System;

class Program
{

    delegate void MyDelegate(int n);

    void Foo(int n)
    {
        Console.WriteLine("n = {0}", n)
    }

    static void Main(string[] args)
    {
        MyDelegate d = new MyDelegate(Foo);
        d += Foo; // add Foo again

        d.Invoke(3); // Foo is invoked twice as Foo appears two times in invocation list

    }
}

But when I look at MSDN Delegate, MulticastDelegate I can't find any definition of the += operator. How is it that is just works? Auto-generated compiler magic?

jensa
  • 2,792
  • 2
  • 21
  • 36
  • 2
    I flagged this as a duplicate of [Why don't I see the += operator overloaded on System.Delegate?](http://stackoverflow.com/q/28391414/1364007) but this question has (in my view) better answers. – Wai Ha Lee Jan 06 '16 at 09:57
  • @WaiHaLee I agree, I think the duplicate should be marked the other way around. – StayOnTarget Feb 20 '19 at 17:28

2 Answers2

55

It's not an operator on the delegate type itself, in IL terms - it's defined in the language specification, but you wouldn't find it using reflection. The compiler turns it into a call to Delegate.Combine. The reverse operation, using - or -=, uses Delegate.Remove.

At least, that's how it's implemented when C# targets .NET, as it almost always does. In theory, this is environment-specific - the language specification doesn't require that a compiler uses Delegate.Combine or Delegate.Remove, and a different environment may not have those methods.

From the C# 5 specification, section 7.8.4 (addition):

The binary + operator performs delegate combination when both operands are of some delegate type D. (If the operands have different delegate types, a binding-time error occurs.) If the first operand is null, the result of the operation is the value of the second operand (even if that is also null). Otherwise, if the second operand is null, then the result of the operation is the value of the first operand. Otherwise, the result of the operation is a new delegate instance that, when invoked, invokes the first operand and then invokes the second operand. For examples of delegate combination, see §7.8.5 and §15.4. Since System.Delegate is not a delegate type, operator + is not defined for it.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks, this confirms what I mean by "compiler-magic", that the compiler somehow translates the "+=" to something that is defined and readable on MSDN. – jensa Nov 27 '15 at 21:27
  • 2
    @jensa If that is your definition of "compiler-magic" then many features are compiler magic. For example `==` is not defined on System.Object but the language defines such an operator. – Mike Zboray Nov 27 '15 at 21:29
  • 2
    @mikez: I think it's entirely reasonable to draw a distinction between language-specified operators - including the reference equality `==` as you mention, and also string concatenation - and those which are library-provided, like `DateTime +(DateTIme, Timespan)`. – Jon Skeet Nov 27 '15 at 21:32
  • 1
    @mikez Yeah I guess, I'm coming from a C++ background where very little is language-specified in terms of operators (you get your assignment operator for class types basically), hence my confusion. – jensa Nov 27 '15 at 21:35
  • What is the reason that C# delegate is not directly mapped to `System.MulticastDelegate`? Simple types (`int`, `double` etc.), `string` are explicitly defined as aliases to corresponding `System.*` types. – Jakub Lortz Nov 27 '15 at 22:24
  • 1
    @JakubLortz: The delegate keyword isn't a type like decimal, string etc. It's used to declare other delegate types, and anonymous methods. – Jon Skeet Nov 28 '15 at 07:12
  • @MikeZboray Compilers are inherently magic. That's why only wizards create them. – Adam Johnston Aug 17 '19 at 05:56
  • @jensa In C++ language provides you tons of operators not defined anywhere, but the standard. i.e. all arithmetic operators on primitives and pointers. Also `operator &`, `operator ->`, `operator ,`. Some have even special meaning (short-circuiting `operator &&`) – OwnageIsMagic Aug 07 '22 at 20:11
3

It's the same as with Int32, String etc. The + operator is defined implicitly by the language.

You can check the source code of Delegate, MulticastDelegate, Int32 etc. There are no overloads of operator + there, that's why it doesn't appear in the MSDN documentation.

From C# language spec, section 7.8.4:

The predefined addition operators are listed below.

(...)

• Delegate combination. Every delegate type implicitly provides the following predefined operator, where D is the delegate type:

D operator +(D x, D y);

There is a difference between simple types and delegates. The C# language specification doesn't require that a delegate is implemented using System.Delegate

4.2.7 Delegate types

A delegate is a data structure that refers to one or more methods. For instance methods, it also refers to their corresponding object instances. The closest equivalent of a delegate in C or C++ is a function pointer, but whereas a function pointer can only reference static functions, a delegate can reference both static and instance methods. In the latter case, the delegate stores not only a reference to the method’s entry point, but also a reference to the object instance on which to invoke the method. Delegate types are described in §15.

Note that there is no mention of System.Delegate there. Compare it with Section 4.1.4 Simple types:

C# provides a set of predefined struct types called the simple types. The simple types are identified through reserved words, but these reserved words are simply aliases for predefined struct types in the System namespace, as described in the table below.

Reserved word Aliased type

sbyte System.SByte
byte System.Byte
short System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
char System.Char
float System.Single
double System.Double
bool System.Boolean
decimal System.Decimal

Or Section 4.2.4 The string type

(...)

The keyword string is simply an alias for the predefined class System.String.

So resolving the + operator for delegates to Delegate.Combine is an implementation detail of C# compilers in .NET framework.

Jakub Lortz
  • 14,616
  • 3
  • 25
  • 39