Search code examples
c#delegatesoperator-overloadingmulticastdelegate

Getting "Operator '+' cannot be applied to operands of type 'method group' and 'method group'" when trying to chain delegatees (multicast delegate)


The following code

public class TypeTests {
    delegate int LogMessageDelegate(string message);
    
    int LogMessageToConsoleReturn1(string msg) {
        Console.WriteLine($"{msg} return 1");
        return 1;
    }

    int LogMessageToConsoleReturn2(string msg) {
        Console.WriteLine($"{msg} return 2");
        return 2;
    }

    [Fact]
    public void DelegateInvokesMethod() {
        LogMessageDelegate log;
        // log = LogMessageToConsoleReturn1; // assign to a method group
        // log += LogMessageToConsoleReturn2; // multicast using += works just fine
        log = LogMessageToConsoleReturn1 + LogMessageToConsoleReturn2; // multicast using + causes CS0019 compiler error
        Assert.Equal(2, log("Hello"));
    }
}

is causing a CS0019 compiler error with the following message

Operator '+' cannot be applied to operands of type 'method group' and 'method group'

It should work per How to combine delegates (Multicast Delegates) which states

multiple objects can be assigned to one delegate instance by using the + operator.

and furthermore provides the example

multiDel = hiDel + byeDel;

where hiDel and byeDel are each a method group. [EDIT: I think I was mistaken; hiDel and byeDel are each a delegate, not a method group, by this point in the code.]


Using += works. I.e., if I change the test to

    [Fact]
    public void DelegateInvokesMethod() {
        LogMessageDelegate log;
        log = LogMessageToConsoleReturn1; // assign to a method group
        log += LogMessageToConsoleReturn2; // multicast using += works just fine
        // log = LogMessageToConsoleReturn1 + LogMessageToConsoleReturn2; // multicast using + causes CS0019 compiler error
        Assert.Equal(2, log("Hello"));
    }

then it compiles, runs, and passes just fine.


Solution

  • You need to have instances of your delegate before you combine them unfortunately. Below I named them first and second.

    public class TypeTests
    {
        delegate int LogMessageDelegate(string message);
    
        int LogMessageToConsoleReturn1(string msg)
        {
            Console.WriteLine($"{msg} return 1");
            return 1;
        }
    
        int LogMessageToConsoleReturn2(string msg)
        {
            Console.WriteLine($"{msg} return 2");
            return 2;
        }
    
        [Fact]
        public void DelegateInvokesMethod()
        {
            LogMessageDelegate log, first, second;
            // log = LogMessageToConsoleReturn1; // assign to a method group
            // log += LogMessageToConsoleReturn2; // multicast using += works just fine
            first = LogMessageToConsoleReturn1;
            second = LogMessageToConsoleReturn2;
            log = first + second; // multicast using + causes CS0019 compiler error
            Assert.Equal(2, log("Hello"));
        }
    }
    

    But there's also another way to do it, a small trick:

    log = (LogMessageDelegate)LogMessageToConsoleReturn1 + LogMessageToConsoleReturn2;