Why do static lambda’s (c# 9) still have a target?

Why do static lambda’s (c# 9) still have a target?


7

Static lambda’s introduced in c# 9 allow us to mark a lambda expression as static to prevent it from capturing instance state.

However when you check the .Target property on the lamda it is still set, which is different to when you set an Action to a static method which has no target.

Action action = static () => Console.WriteLine("test");
if(action.Target != null)
{
    // action unexpectedly holds a reference
}

Background:
I’m trying to make a eventing system (not tied to the current event syntax) that uses weak references without needing reflection (MethodInfo), I was checking that .Target was null, but that doesn’t work for static lambda. Where the static lambda .Target is set to a nested singleton.

Share
Improve this question

4

  • 1

    Could you please confirm that "holds a reference to the current class" is indeed true? To me it looks like Target points to autogenerated nested class instance (hence unrelated to "the current class")… (Also clearly at least 4 people verified the behavior and found that indeed Target points to the main class' instance… any of upvoters could provide details to reproduce the behavior?)

    – Alexei Levenkov

    10 hours ago


  • @AlexeiLevenkov Yes your correct, will update question.

    – trampster

    10 hours ago


  • Consider to also clarify what exactly your concerns now… "Why C# creates class even my action does not have state on its own" or "Does class autogenerated for static action still refer to its "parent" class" or… (current answer could easily be "just because they can")

    – Alexei Levenkov

    10 hours ago

  • 1

    @AlexeiLevenkov thanks for the suggestion, I added some background to my question.

    – trampster

    9 hours ago

1 Answer
1

Reset to default


8

Because static delegates are slower than delegates to instance methods.

Here’s the source straight from the horse’s mouth: https://github.com/dotnet/roslyn/issues/20315#issuecomment-309583018

Here’s an issue I opened awhile ago that would remove the need to do this: https://github.com/dotnet/runtime/issues/58955

The reason is deep in the guts of calling conventions. All delegate invocations are member function calls on the delegate method. In the ancestral platform, a static delegate compiled to only two instructions (pop and jmp indirect); however modern platforms pass arguments in registers rather than on the stack. This means an instance delegate invocation can compile to two instructions (mov and jmp indirect); however a static delegate has to compile to generate entire stack frame and copy all arguments, so it can remove the instance parameter from the argument list.

Share
Improve this answer

1

  • 1

    Can you please give more detail in the answer itself? The sentence, "Because static delegates are slower than delegates to instance methods," seems incomplete and inadequate to me.

    – Enigmativity

    6 hours ago




Leave a Reply

Your email address will not be published. Required fields are marked *