Search Unity

Can't figure any delegate/event/lambda stuff

Discussion in 'Scripting' started by Kensei, Aug 23, 2014.

  1. Kensei

    Kensei

    Joined:
    Apr 26, 2013
    Posts:
    63
    I've been reading a bunch of articles over the net including this thread and watched quite a few videos, and I seriously can't figure this out.

    Everybody first explains the delegate, which all I can grasp from it is that it just encapsulates some method. Then they instantiate a ton of stuff related to this delegate jumping around classes, and I really can't figure this part out, which reference goes where etc. And then voila, everything is working.

    Second thing explained is the EVENT keyword, which from what it seems basically tells the compiler that you can't use = and can only go for += or -=, so yeah that one I get.

    Now here comes the stuff I don't understand, since apparently I'm not the only one that is super confused about delegates with all them countless information pockets giving employee examples, there's this Anonymous syntax or something that pretty much does some arcane voodoo magic and doesn't need any names at all.

    And then finally there's the lambda syntax, which on top of it all seems to be different for Unity with Action<> and Func<>. I thought all you needed is (args) => {expression}, so what gives about all the = () => stuff?

    I dunno maybe I can't get it because the whole delegate thing is kind of alien to me, but it seems like a pretty powerful feature.

    Lets say there's balls falling from the screen and the player collects them for score. Now I know there's a simple way to make this work, but how would this work with delegates/lambda things? Or am I misunderstanding the keyword EVENT? In my head I imagine an event being a bool, as in, something happened vs still hasn't, is this the wrong way to think about it?

    If a brick falls on a robots head, that's an event right? The brick fell and collided with the bot, so it should return true.

    I am seriously confused about this. Any clarification on the subject is appreciated.
     
  2. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    () => stuff simply means no arguments are passed to the code block.

    A lot of the stuff you are talking about is for LINQ. Thats one of the main places you use lambdas.
     
  3. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Oh God... This could fill about a whole semester of programming in university.

    A pointer is a variable that contains the memory address of another variable.

    A function is like a variable, as the collection of instruction are stored in memory too.

    So, a delegate is a pointer towards a function. In the case of managed languages - like C# - the delegate is typed and contains the information about the function signature, such as the parameters and its return type.

    When you define a delegate in C#, using the delegate keyword, you define a valid function signature, like a variable type.

    And event is syntax sugar coating. In background, there's two method and list of delegate. It's like a Get/Set - but it's Add/Remove - that could get a specific delegate type. When you do += it add your delegate to that list and when you do -= it removes it.

    When you do

    Code (CSharp):
    1. if (myEvent != null)
    2.     myEvent();
    It is also syntax sugarcoating, as in background it loops in all the list of delegate and invoke each one after the other.

    Lambda instruction are even more sugar on top. They are a function, plain and simple, but are written in a shortcut way;

    Code (CSharp):
    1. public bool MyFunc(int value) { return value == 0; }
    is exactly the same as

    Code (CSharp):
    1. x => x==0
    In the end, once compiled, the function and the lambda will generate the same IL instruction.
     
  4. Fraconte

    Fraconte

    Joined:
    Dec 6, 2013
    Posts:
    327
    Kensei likes this.
  5. Kensei

    Kensei

    Joined:
    Apr 26, 2013
    Posts:
    63
    Sorry I didn't formulate my question properly. I get the concept of delegates. However I can't understand the syntax.
    Is this the right way to go?
    Code (CSharp):
    1. public class One
    2. {
    3. //declare the delegate
    4. public delegate void Enter (int x);
    5. public static event Enter entered; // Mark the delegate as an event, is static needed?
    6. }
    7. public class Two
    8. {
    9. //Now I have to subscribe to the event in class one.
    10. One.entered += Method; // Do I have to match the event signature? Or just the parameters?
    11. private void Method (int y)
    12. {
    13. //Do stuff.
    14. }
    15.  
    16. }
    That the way? If it is, when will the event fire? I mean the delegate takes any integer, so how would it know? I can understand how this would work as a bool, but what about things like when a player moves the mouse and I want the event to publish the input.axis? Is that even legit? I'm still digging around the net, and this anonymus and lambda declaration just seem like magic to me.
     
  6. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Code (CSharp):
    1.     public class One
    2.     {
    3.         public delegate void Enter (int x);
    4.  
    5.         // Static is only needed if you want it to be static. It's like a variable.
    6.         // If the event is related to an instance, it should not be static.
    7.         public event Enter OnEntered;
    8.  
    9.         public void Enter()
    10.         {
    11.             int myInt = 0;
    12.             if (DateTime.Now.IsDaylightSavingTime())
    13.                 myInt = 1;
    14.  
    15.             // It is up to you to fire an event.
    16.             if (OnEntered != null)
    17.                 OnEntered(myInt);
    18.         }
    19.     }
    20.  
    21.     public class Two
    22.     {
    23.         private One one;
    24.  
    25.         public Two()
    26.         {
    27.             one = new One();
    28.             one.OnEntered += Method;
    29.         }
    30.  
    31.         private void Method (int y)
    32.         {
    33.             if (y == 1)
    34.                 Debug.Log("Day Time Saving!");
    35.             else
    36.                 Debug.Log("No saving.");
    37.         }
    38.     }
     
    Kensei likes this.
  7. Fraconte

    Fraconte

    Joined:
    Dec 6, 2013
    Posts:
    327
    I think the "static" is used to let subscribe to the event also when the event class is not yet initialized.
     
  8. Kensei

    Kensei

    Joined:
    Apr 26, 2013
    Posts:
    63
    OOOOOOOOOOOOOOOH I get it now...thanks LightStriker dude rly helped me understand this :D. That was a very clear example. Daium delegates are pretty neat, xpecially this decoupling stuff. I still can't figure the lambda thing out, but i suppose it will come in time. Also it seems kinda hard to read even though it's easy to write. I dunno it just seems weird to me, just writing x => x ==0;

    Anyway, thank you very much for the time to help me out man. Very much appreciated.
     
  9. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    What, no explanation of closures?! Feh! ;D

    Honestly, once you get delegates they're super useful. Try not to get too fancy.
     
  10. Kensei

    Kensei

    Joined:
    Apr 26, 2013
    Posts:
    63
    What closures? Yeah I'll try not to overcomplicate things ^^ Gotta get used to them. Also, thanks to fraconte for the link.
     
  11. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    In all my years of coding, I never needed full closures. I see them as bad form to begin with. Well, lambda are closures too... Just not with the full syntax. Frankly, outside of Linq, I never used a lambda. It just makes maintenance harder.
     
  12. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    Well, sometimes lambdas are closures and sometimes not. It depends on the function defined in the lambda. They're pretty insanely useful at times. But yeah, probably not a discussion point for this thread since they can get extremely tricky.