0

I tried to unsubscribe from a lambda within itself. I used the MethodInfo class for getting information about a lambda and the Delegate.CreateDelegate method for creating the same method as a lambda. So it works fine if a lambda created in one of the class methods that contains the event i use but doesn't work in another class method (binding exception).

Here's the code:

public class TestClass
{
    public event Action SomeEvent;
    public void OnSomeEvent()
    {
        if (SomeEvent != null)
        {
            SomeEvent();
        }
    }
    public TestClass()
    {
        //IT WORKS FINE!!!
        //SomeEvent += () =>
        //{
        //    Console.WriteLine("OneShotLambda");
        //    MethodInfo methodInfo = MethodInfo.GetCurrentMethod() as MethodInfo;
        //    Action action = (Action)Delegate.CreateDelegate(typeof(Action), this, methodInfo);
        //    SomeEvent -= action;
        //};
    }
}

class Program
{
    static void Main(string[] args)
    {
        TestClass t = new TestClass();
        t.SomeEvent += () =>
            {
                Console.WriteLine("OneShotLambda");
                MethodInfo methodInfo = MethodInfo.GetCurrentMethod() as MethodInfo;
                //GOT AN ERROR
                Action action = (Action)Delegate.CreateDelegate(typeof(Action), t, methodInfo);
                t.SomeEvent -= action;
            };
        t.OnSomeEvent();
        t.OnSomeEvent(); //MUST BE NO MESSAGE
    }
}
shadeglare
  • 7,006
  • 7
  • 47
  • 59

1 Answers1

6

The reason why it doesn't work is that you pass in t as the second parameter to CreateDelegate when you should pass null. This is due to the fact that the method created for the lambda will be a static method. Otherwise it couldn't be used from the static Main method. And the documentation clearly states that you need to pass null for static methods.

Having said that, you would be better off doing it differently:

TestClass t = new TestClass();
Action eventHandler = null;
eventHandler = () =>
               {
                   Console.WriteLine("OneShotLambda");
                   t.SomeEvent -= eventHandler;
               }
t.SomeEvent += eventHandler;

This code is more readable and understandable and additionally performs better.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • If I pass null then t.SomeEvent -= action doesn't remove the current lambda from the event and there's no exception either (very strange). So I will use your solution. Thanks. – shadeglare Oct 19 '12 at 09:33