0

I have an Action like this:

    Action<string> myAction;

I add a method in OnEnable() this way:

    myAction += param => 
    {
        Debug.Log(param);
    }

And later in OnDisable() I would like to remove it. How to do it?

e1ka
  • 1
  • 3
  • 3
    You don't, not like that. In your specific example, you can do `myAction += Debug.Log;`, and then `myAction -= Debug.Log;`. In the more general case, you can either 1) `Action a = x => Debug.Log(x);` and then `myAction += a` and `myAction -= a`, or 2) Write a method `private static void MyAction(string s) { .. }`, then `myAction += MyAction;` and `myAction -= MyAction;` – canton7 Jul 15 '21 at 16:00
  • You can't! Lambda expressions **can not** be unsubscribed! – derHugo Jul 15 '21 at 16:07
  • Ok, I'll try it tomorrow. Thanks. – e1ka Jul 15 '21 at 16:09
  • @derHugo Considering canton posted a comment 7 minutes before you showing specifically how to do it, it's pretty demonstrably not impossible. – Servy Jul 15 '21 at 16:10
  • 2
    @Servy None of my bits of code unsubscribe a *lambda expression*. They all either unsubscribe a method group, or a variable holding a delegate instance. – canton7 Jul 15 '21 at 16:13
  • @Servy I didn't say it's impossible .. what I say you is you can't unsubscribe Lambda expressions .. have to use another way .. a delegate reference != Lambda expression .. and also an explicit method != lambda expression ;) – derHugo Jul 15 '21 at 16:13
  • @canton7 the lambda *is* a delegate though, and the delegate is defined by a lambda. That's like saying you didn't unsubscribe anything you used the `-=` operator. – Servy Jul 15 '21 at 16:17
  • @derHugo But you *can* unsubscribe lambda expressions. You saying you can't is just false. A lambda resolves to a delegate instance. That's just what it is, whenever it doesn't resolve to an `Expression`, which this doesn't. Had you said something like, "you can't unsubscribe a lambda without storing the reference to it somewhere" then that would have been factually accurate. – Servy Jul 15 '21 at 16:18
  • @Servy let me rephrase this: What OP is using is an anonymous lambda expression and the way it was subscribed without storing any reference to it it is impossible to unsubscribe it later since the reference is lost .. you probably refer to a method in expression body notation like `private void DoSomething (string bla) => Debug.Log(bla);` or similar – derHugo Jul 15 '21 at 16:20
  • 1
    @Servy A "lambda" refers to the syntax "stuff => otherStuff", which can be used to produce an instance of a `Delegate`, or an instance of a `System.Linq.Expressions.Expression`. The term "lambda expression" makes this even clearer: it's an *expression*. A lambda is *not* a delegate, strictly. You cannot safely use a lambda on the RHS of a `-=` to unsubscribe from an event – canton7 Jul 15 '21 at 16:20
  • @derHugo Yes. That's a factually accurate statement. It's not that they can't unsubscribe a lambda from the delegate, they just didn't do it correctly (which they stated as much in the question, so I'm not sure why it'd be useful to tell them that). They can absolutely do it. – Servy Jul 15 '21 at 16:22
  • So I'd argue that @derHugo is correct: if you subscribe to an event using a *lambda expression*, you're doing `x += y => z` (as opposed to `x += MethodGroup` or `x += delegateInstance`). This means there's no way to unsubscribe. – canton7 Jul 15 '21 at 16:23
  • @canton7 Sure, but the lambda is resolved to a delegate regardless of whether you store it in a local variable before adding it to another delegate. If you want to be that strict with your language (which I don't consider productive here) then you never "subscribe a lambda to a delegate" you just subscribe a delegate defined by a lambda. You *can* safely use a lambda on the RHS of a `-=` operator. It'll never fail or produce undefined behavior, it just won't remove anything. – Servy Jul 15 '21 at 16:25
  • 1
    @Servy without wanting to appear to picky here ;) But the last sentence .. I as a developer would define the `it just won't remove anything` as the unexpected/undesired behavior in this case ;) so yes sure you can "unsubscribe" something even when it was never added .. but it is clearly not OPs intend ^^ I would still claim there is a slight difference between a pure lambda expression as an anonymous function and a delegate using an expression body. But yeah in general the important fact is we need the reference otherwise there is no way. – derHugo Jul 15 '21 at 16:27
  • 1
    @canton7 "if you subscribe to an event using a lambda expression" By your own strict usage of definitions, that's not possible. You can't subscribe a lambda to an event, you can only subscribe a delegate that was defined by a lambda to an event. Another factually correct statement you could make would be that you need to have stored that delegate somewhere to unsubscribe it. *If* you choose to not store the delegate instance anywhere, then you can't unsubscribe it. – Servy Jul 15 '21 at 16:28
  • @derHugo But canton said it wouldn't be safe. Not that it wouldn't have some particular effect. "Not being safe" would imply undefined behavior, or an exception. An operation that reliably does nothing is *safe*, even if it's not useful. I can't think of anything *safer* that an operation that for sure does nothing. – Servy Jul 15 '21 at 16:29
  • @Servy Well, sometimes it does something, and sometimes it doesn't; it depends on whether the same lambda instance is reused by the runtime, which depends on whether the lambda captures variables. That seems a bit dangerous to me. Also, even if it always did nothing, the fact that it appears to do something seems dangerous: it can make a programmer feel falsely secure about everything being cleaned up; it might hide the origin of a bug later on. – Oscar Abraham Jul 16 '21 at 03:53
  • @OscarAbraham Given that it was coming from someone trying to be extremely pedantic and picking apart my phrasing, that's an *extremely* unconventional and confusing usage of the term, if that was in fact their intended meaning. It's just worlds more clear to say that it won't remove the delegate, since that's what they were clearly trying to convey. And it's not like I'm *unaware* that writing that code doesn't remove the handler. It's just all around not a useful thing to say. – Servy Jul 16 '21 at 14:50

0 Answers0