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?
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.
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.