Method groups and lambdas whose shape Action/Func cannot express (ref
parameter or return kinds, and with pointers, params, or default values
the non-generic fallback) get compiler-synthesized delegate types:
<>A{flags} (void-returning), <>F{flags} (value-returning), and
<>f__AnonymousDelegateN. Their names are unspeakable, so declared
variables printed the escaped type name and did not compile.
Detect them (generated name in one of the three families, delegate
kind, CompilerGenerated, no namespace), declare locals of such types as
'var', hide the synthesized type definitions, name the locals 'anon',
and let DelegateConstruction accept the synthesized methods. Since the
site is then typed solely by the anonymous function's natural type,
lambda syntax is mandatory: 'delegate {}' without a parameter list has
no natural type, and the 'delegate' form cannot declare a return type.
When the return type C# would re-infer from the emitted body differs
from the delegate's (a widened return, or a discarded value in an
expression body), the lambda declares the delegate's return type
explicitly (C# 10).
The LambdaReturnTypes fixture pins that last part: in a delegate-typed
context an explicit return type leaves no trace in metadata, so the
syntax only matters for natural-typed lambdas. Every case has a ref
parameter, which makes 'var' the only legal declaration, and the return
type appears exactly where it is load-bearing - widening the body's type
to object, or forcing void over an inferable int - and is omitted where
inference recovers it.
Gated by a new NaturalTypeForLambdaAndMethodGroup setting (C# 10).
Assisted-by: Claude:claude-fable-5:Claude Code