A Roslyn analyzer that allows you to enforce a no-capture policy for passing lambdas to your methods by decorating them with a special attribute.
Install the HellBrick.NoCapture package from NuGet
Decorate the methods or the parameters that you don't want the callers to pass capturing lambdas to with the
[NoCapture]attribute:
[NoCapture]publicstaticIEnumerable<TOut>Select<TIn,TOut,TArg>(thisIEnumerable<TIn>sequence,TArgargument,Func<TIn,TArg,TOut>selector){foreach(TIniteminsequence)yieldreturnselector(item,argument);}publicstaticIEnumerable<TOut>Select<TIn,TOut>(thisIEnumerable<TIn>sequence,[NoCapture]Func<TIn,TOut>selector)=>sequence.Select(selector,(item,innerSelector)=>innerSelector(item));// ...publicclassCaller{privatereadonlyint[]_numbers={64,128,256};privatereadonlyint_field=42;publicvoidCallSite(intargument){// Error: Select( selector ) requires a non-capturing lambda. Captured variables: this._numbers.Select( x =>x+_field);// Error: Select( selector ) requires a non-capturing lambda. Captured variables: this, argument._numbers.Select("",(x,_)=>x+_field+argument);}}At the moment, only the lambdas defined inline in the argument list are checked for the violations of the [NoCapture] attribute.
For instance, the following call site, if added to the previous example, will trick the analyzer into a false negative:
publicvoidAnotherCallSite(){// No error yet.Func<int,int>lambda= x =>x+_field;_numbers.Select(lambda);}