PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, November 4, 2022

[FIXED] How and where are anonymous methods without parameters used?

 November 04, 2022     anonymous-methods, c#, lambda     No comments   

Issue

When comparing anonymous methods to lambda expressions, I've seen explanations that anonymous methods provide flexibility.

Flexibility here means that you can omit parameters from anonymous methods.

// inflexible anonymous method

Action<int> action = delegate(int number) 
{ 
    Console.WriteLine($"Anonymous method: {number}"); 
}
action(1234);

// Output
// Anonymous method: 1234
// flexible anonymous method

Action<int> action = delegate 
{ 
    Console.WriteLine("Anonymous method"); 
}
action(1234);

// Output
// Anonymous method
Action<int> action = (number) => 
{ 
    Console.WriteLine($"Lambda expression: {number}"); 
};
action(1234);

// Output
// Lambda expression: 1234

However, I have two questions.

First, how does an anonymous method with an omitted parameter use the passed value? (1234 here)

Second, where do you use the flexibility that anonymous methods provide?


Solution

I'll only answer the first question. The second question is highly opinion based, depends on context and at best I can offer incomplete / insufficient examples. Refer to the examples offered in Action Delegate. One use case is Composability

How does an anonymous method with an omitted parameter use the passed value?

It doesn't. The generated IL (intermediate language) doesn't account in any way for the provided argument. Which seems logical because if it does, it needs to have knowledge about all the callers of that method.

IL_0000:  ldsfld      UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_0005:  brtrue.s    IL_0018
IL_0007:  ldnull      
IL_0008:  ldftn       UserQuery.<Main>b__0
IL_000E:  newobj      System.Action<System.Int32>..ctor
IL_0013:  stsfld      UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_0018:  ldsfld      UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_001D:  stloc.0     // action
IL_001E:  ldloc.0     // action
IL_001F:  ldc.i4      D2 04 00 00 
IL_0024:  callvirt    System.Action<System.Int32>.Invoke
IL_0029:  ret         

<Main>b__0:
IL_0000:  ldstr       "Anonymous method"
IL_0005:  call        System.Console.WriteLine
IL_000A:  ret         

On IL_001F the value 1234 is pushed on the stack. In <Main>b__0 there is no "pop" from the stack. So the value is lost.

If you would have a method that takes an int, like so void test(int arg) the IL would look like:

test:
IL_0000:  ldstr       "Test method"
IL_0005:  ldarg.1     
IL_0006:  box         System.Int32
IL_000B:  call        System.Console.WriteLine
IL_0010:  ret 

Here it does "pop" the argument of the stack in IL_005.

It is worth remembering that a delegate is a generated type that derives from System.Delegate and there is an implementation detail you see on line IL_0024.

The common language runtime provides an Invoke method for each delegate type, with the same signature as the delegate. You do not have to call this method explicitly from C#, Visual Basic, or Visual C++, because the compilers call it automatically.

Do note that your first and last example return the same IL for the .Net 6 compiler, which you can inspect here



Answered By - rene
Answer Checked By - Gilberto Lyons (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing