Convert this delegate to an anonymous method or lambda

24,914

Solution 1

That's a well known error message. Check the link below for a more detailed discussion.

http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/

Basically you just need to put a cast in front of your anonymous delegate (your lambda expression).

In case the link ever goes down, here is a copy of the post:

They are Anonymous Methods, not Anonymous Delegates.
Posted on December 22, 2007 by staceyw1

It is not just a talking point because we want to be difficult. It helps us reason about what exactly is going on. To be clear, there is *no such thing as an anonymous delegate. They don’t exist (not yet). They are "Anonymous Methods" – period. It matters in how we think of them and how we talk about them. Lets take a look at the anonymous method statement "delegate() {…}". This is actually two different operations and when we think of it this way, we will never be confused again. The first thing the compiler does is create the anonymous method under the covers using the inferred delegate signature as the method signature. It is not correct to say the method is "unnamed" because it does have a name and the compiler assigns it. It is just hidden from normal view. The next thing it does is create a delegate object of the required type to wrap the method. This is called delegate inference and can be the source of this confusion. For this to work, the compiler must be able to figure out (i.e. infer) what delegate type it will create. It has to be a known concrete type. Let write some code to see why.

private void MyMethod()
{
}

Does not compile:

1) Delegate d = delegate() { };                       // Cannot convert anonymous method to type ‘System.Delegate’ because it is not a delegate type
2) Delegate d2 = MyMethod;                         // Cannot convert method group ‘MyMethod’ to non-delegate type ‘System.Delegate’
3) Delegate d3 = (WaitCallback)MyMethod;   // No overload for ‘MyMethod’ matches delegate ‘System.Threading.WaitCallback’

Line 1 does not compile because the compiler can not infer any delegate type. It can plainly see the signature we desire, but there is no concrete delegate type the compiler can see. It could create an anonymous type of type delegate for us, but it does not work like that. Line 2 does not compile for a similar reason. Even though the compiler knows the method signature, we are not giving it a delegate type and it is not just going to pick one that would happen to work (not what side effects that could have). Line 3 does not work because we purposely mismatched the method signature with a delegate having a different signature (as WaitCallback takes and object).

Compiles:

4) Delegate d4 = (MethodInvoker)MyMethod;  // Works because we cast to a delegate type of the same signature.
5) Delegate d5 = (Action)delegate { };              // Works for same reason as d4.
6) Action d6 = MyMethod;                                // Delegate inference at work here. New Action delegate is created and assigned.

In contrast, these work. Line 1 works because we tell the compiler what delegate type to use and they match, so it works. Line 5 works for the same reason. Note we used the special form of "delegate" without the parens. The compiler infers the method signature from the cast and creates the anonymous method with the same signature as the inferred delegate type. Line 6 works because the MyMethod() and Action use same signature.

I hope this helps.

Also see: http://msdn.microsoft.com/msdnmag/issues/04/05/C20/

Solution 2

What Mark said.

The problem is that Do takes a Delegate parameter. The compiler can't convert the anonymous methods to Delegate, only a "delegate type" i.e. a concrete type derived from Delegate.

If that Do function had took Action<>, Action<,> ... etc. overloads, you wouldn't need the cast.

Solution 3

The problem is not with your delegate definition, it's that the parameter of the Do() method is of type System.Delegate, and the compiler generated delegate type (FakeSave) does not implicitly convert to System.Delegate.

Try adding a cast in front of your anonymous delegate:

Expect.Call(delegate { _dao.Save(t); }).Do((Delegate)delegate { t.Message = "I drink goats blood"; });
Share:
24,914
Abhishek
Author by

Abhishek

I have been a senior developer with a focus on architecture, simplicity, and building effective teams for over ten years. As a director at Surge consulting I was involved in many operational duties and decisions and - in addition to software development duties - designed and implemented an interview processes and was involved in community building that saw it grow from 20 to about 350 developers and through an acquisition. I was then CTO setting up a dev shop at working closely with graduates of a coding bootcamp on both project work and helping them establish careers in the industry. Currently a Director of Engineering at findhelp.org your search engine for finding social services. I speak at conferences, have mentored dozens of software devs, have written popular articles, and been interviewed for a variety of podcasts and publications. I suppose that makes me an industry leader. I'm particularly interesting in companies that allow remote work and can check one or more of the following boxes: Product companies that help people in a non-trite manner (eg I'm not super interested in the next greatest way to get food delivered) Product companies that make developer or productivity tooling Funded startups that need a technical co-founder Functional programming (especially Clojure or Elixir) Companies trying to do something interesting with WebAssembly

Updated on July 09, 2022

Comments

  • Abhishek
    Abhishek almost 2 years

    I am new to all the anonymous features and need some help. I have gotten the following to work:

    public void FakeSaveWithMessage(Transaction t)
    {
        t.Message = "I drink goats blood";
    }
    
    public delegate void FakeSave(Transaction t);
    
    public void SampleTestFunction()
    {
        Expect.Call(delegate { _dao.Save(t); }).Do(new FakeSave(FakeSaveWithMessage));
    }
    

    But this is totally ugly and I would like to have the inside of the Do to be an anonymous method or even a lambda if it is possible. I tried:

    Expect.Call(delegate { _dao.Save(t); }).Do(delegate(Transaction t2) { t2.Message = "I drink goats blood"; });
    

    and

    Expect.Call(delegate { _dao.Save(t); }).Do(delegate { t.Message = "I drink goats blood"; });
    

    but these give me

    Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type** compile errors.

    What am I doing wrong?


    Because of what Mark Ingram posted, seems like the best answer, though nobody's explicitly said it, is to do this:

    public delegate void FakeSave(Transaction t);
    
    Expect.Call(delegate { _dao.Save(t); }).Do( new FakeSave(delegate(Transaction t2) { t.Message = expected_msg; }));
    
  • Abhishek
    Abhishek over 14 years
    This doesn't work delegate {} is an anonymous function - it is not a type. System.Delegate is the abstract base class that is the implicit base of all delegate types declared. There's really 3 different uses of the word delegate here! You can downcast any delegate type (such as EvantHandler, Action, Func<R>) to Delegate but you have to actually create a delegate type first!
  • BlueRaja - Danny Pflughoeft
    BlueRaja - Danny Pflughoeft over 13 years
    Good link, but I still don't understand why the compiler doesn't cast it automagically (like it does with lambda syntax)
  • Adam McKee
    Adam McKee about 13 years
    @BlueRaja, the title of the post should be a clue - "They are Anonymous Methods, not Anonymous Delegates."
  • Adam McKee
    Adam McKee almost 13 years
    I've copied the text into the answer for future reference.