CSharp 10 Features

Last Updated: 3/21/2022

Lambda Expression Improvements

You can declare variable with var keyword and assign value or object to it, the compiler then infers the type. Likewise you can assign a lambda expression to var keyword which the compiler can infer.

  • The compiler can infer a delegate type from the lambda expression or method group when lambda expressions have a natural type.
  • When the compiler can't infer it, lambda expressions may declare a return type.
  • Attributes can be applied to lambda expressions.

Natural Type for Lambda

You can use lambda expressions without declaring a variable of a delegate type. The compiler may infer the delegate type from the lambda expression when it has natural type.

Declare var parse = (string s) => int.Parse(s);

Instead Func<string, int> parse = (string s) => int.Parse(s);

Assign to Less Explicit Type

When a lambda expression has a natural type, it can be assigned to a less explicit type, such as System.Object or System.Delegate

object parse = (string s) => int.Parse(s);   // Func<string, int>
Delegate parse = (string s) => int.Parse(s); // Func<string, int>

Expression Tree

If you assign a lambda expression to System.Linq.Expressions.LambdaExpression, or System.Linq.Expressions.Expression, and the lambda has a natural delegate type, the expression will have a type of System.Linq.Expressions.Expression<TDelegate>

LambdaExpression parseExpr = (string s) => int.Parse(s); // Expression<Func<string, int>>
Expression parseExpr = (string s) => int.Parse(s);       // Expression<Func<string, int>>

Natural types for method groups

Method groups (method names without parameter lists) with exactly one overload have a natural type.

var read = Console.Read; // Just one overload; Func<int> inferred
var write = Console.Write; // ERROR: Multiple overloads, can't choose

Return types for lambdas

The return type of a lambda expression is inferred. For some expressions, that doesn't work:

var choose = (bool b) => b ? 1 : "two"; // ERROR: Can't infer return type

You can specify the return type of a lambda expression before the input parameters. When you specify an explicit return type, you must parenthesize the input parameters

var choose = object (bool b) => b ? 1 : "two"; // Func<bool, object>

Attributes on Lambdas

You can add attributes to a lambda expression, input parameters and return value. The lambda’s parameter list must be parenthesized when there are attributes Attributes on lambda expressions are useful for code analysis, and can be discovered via reflection

//attribute on expression
Func<string, int> parse = [AttributeName(1)] (s) => int.Parse(s);

//attribute on input parameter
var sum = ([Example(1)] int a, [Example(2), Example(3)] int b) => a + b;

//atribute on return value
var inc = [return: Example(1)] (int s) => s++;

References:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions#natural-type-of-a-lambda-expression