+= operator for Delegate
Asked Answered
H

2

44

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?

Haaf answered 27/11, 2015 at 21:20 Comment(2)
I flagged this as a duplicate of Why don't I see the += operator overloaded on System.Delegate? but this question has (in my view) better answers.Guillemette
@WaiHaLee I agree, I think the duplicate should be marked the other way around.Wit
S
58

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.

Schnozzle answered 27/11, 2015 at 21:26 Comment(8)
Thanks, this confirms what I mean by "compiler-magic", that the compiler somehow translates the "+=" to something that is defined and readable on MSDN.Haaf
@Haaf 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.Bobodioulasso
@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).Schnozzle
@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.Haaf
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.Bolivia
@JakubLortz: The delegate keyword isn't a type like decimal, string etc. It's used to declare other delegate types, and anonymous methods.Schnozzle
@MikeZboray Compilers are inherently magic. That's why only wizards create them.Welloiled
@Haaf 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 &&)Plasticity
B
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.

Bolivia answered 27/11, 2015 at 21:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.