Skip to content

Lambda improvements C# 10.0code reduction

Add attributes, explicit return types, and natural type inference to lambdas.

Lambda expressions C# 3.0 are powerful but had limitations compared to regular methods. They couldn't have attributes applied, couldn't specify explicit return types, and required explicit delegate types when assigned to variables.

C# 10.0 brings lambdas closer to methods by allowing attributes, explicit return types, and natural type inference, making them more flexible and reducing the need for explicit delegate declarations.

Code

C#
// Attributes on lambdas
var lambda = [SomeAttribute] (int x) => x * 2;
Action<string> logger = [Conditional("DEBUG")] (msg) => Console.WriteLine(msg);

// Explicit return types
var parse = int (string s) => int.Parse(s);
var getValue = ref int () => ref _field;

// Natural type inference
var add = (int a, int b) => a + b;  // Inferred as Func<int, int, int>
var greet = () => "Hello";          // Inferred as Func<string>
var print = (string s) => Console.WriteLine(s); // Inferred as Action<string>

// Can assign to var without explicit delegate type
var numbers = new[] { 1, 2, 3, 4, 5 };
var doubled = numbers.Select((int x) => x * 2); // Type inference works better

// Return type helps with overload resolution
var choose = object (bool b) => b ? 1 : "string";
C#
// No attributes on lambdas - had to use named methods
int ApplyTransform(int x)
{
    [SomeAttribute]
    return x * 2;
}
Func<int, int> lambda = ApplyTransform;

// No explicit return types
Func<string, int> parse = s => int.Parse(s);
// No ref returns from lambdas at all

// Required explicit delegate type
Func<int, int, int> add = (a, b) => a + b;
Func<string> greet = () => "Hello";
Action<string> print = s => Console.WriteLine(s);

// Had to specify delegate type explicitly
var numbers = new[] { 1, 2, 3, 4, 5 };
var doubled = numbers.Select((Func<int, int>)(x => x * 2));

// Ambiguous without explicit type
Func<bool, object> choose = b => b ? 1 : "string";

Notes

  • Attributes: Apply attributes to lambda parameters, the lambda itself, or the return value
  • Explicit return types: Specify return type before parameters: returnType (params) => expression
  • Natural type: The compiler infers Func<> or Action<> delegate types from lambda signatures
  • Ref returns: Lambdas can now return ref values with explicit return type syntax
  • Natural type inference allows assigning lambdas to var without losing type information
  • Explicit return types help with overload resolution and clarify intent
  • These features make lambdas behave more like regular methods

More information