C# Futures: Lambda Attributes

  • admin 

Attributes are a key part of .NET’s metadata processing capabilities. They are used by compilers, static analyzers, and runtime libraries for a variety of purposes. While normal functions/methods can have attributes, prior to this proposal lambdas and anonymous functions could not.

While in theory any attribute applicable to normal functions/methods could be applied to a lambda, there are new attributes being considered specifically for them. These new attributes control what can be captured by the lambda.

  • CaptureNone: No variables can be captured. The lambda will be compiled as a static function.
  • CaptureThis: Only the ‘this’ pointer will be captured. The lambda will be compiled as a method.
  • CaptureAny: Any local variable can be captured. The lambda will be compiled as part of an anonymous closure object.

When working with performance sensitive code, CaptureAny should be avoided because a new delegate and matching closure object need to be created for each instance. CaptureThis isn’t as bad, but a new delegate still must be allocated. This delegate could result in inefficient memory use if it keeps the outer object alive longer than otherwise necessary. Finally, CaptureNone would only need to create one instance of a delegate that could be reused throughout the life of the application.

When applied to a lambda, the attributes would be used by the compiler or an analyzer to ensure a CaptureNone lambda isn’t accidentally changed to a less efficient type in the future. Essentially the attributes would act as a form of documentation.

This concept isn’t new. For example, in C++ lambdas one has to explicitly list all variables the lambda can capture. The difference here is that the attributes would be optional in C# (unless otherwise enforced by an analyzer).

Under this proposal, attributes can also be added to the parameters on a lambda. In order to avoid confusion, parameters must be enclosed in parens when using attributes. If the attribute is also inside the paren, it applies to the parameter. Attributes outside of the parens apply to the lambda as a whole.

For more information see the Lambda Attributes proposal on GitHub.