Take advantage of static anonymous methods in C# 9 to improve the performance of your .NET applications. Credit: Thinkstock Anonymous functions were introduced in the C# programming language long ago. Although anonymous functions have many benefits, they are not cheap. Avoiding unnecessary allocations matters, and this is why static anonymous functions were introduced in C# 9. In C# 9 lambda or anonymous methods can have a static modifier. This article talks about static anonymous functions and why they are useful, using code examples to illustrate the concepts. To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can download Visual Studio 2019 here. Create a console application project in Visual Studio First off, let’s create a .NET Core console application project in Visual Studio. Assuming Visual Studio 2019 is installed in your system, follow the steps outlined below to create a new .NET Core console application project in Visual Studio. Launch the Visual Studio IDE. Click on “Create new project.” In the “Create new project” window, select “Console App (.NET Core)” from the list of templates displayed. Click Next. In the “Configure your new project” window, specify the name and location for the new project. Click Create. This will create a new .NET Core console application project in Visual Studio 2019. We’ll use this project in the subsequent sections of this article. Anonymous methods are not cheap As I said, anonymous methods are not cheap. You have overheads of invocation of delegates. For example, if your lambda captures the local variable or parameter of the enclosing method, you would have two heap allocations — one allocation for the delegate and a second for the closure. Or if your lambda captures just an enclosing instance state, you would incur just a delegate allocation and hence one heap allocation. If your lambda doesn’t capture anything, or captures only static state, you would incur 0 heap allocations. Let’s understand this with an example. Consider the following code snippet, which illustrates how unintentional allocation might occur in your code. int y = 1; MyMethod(x => x + y); The above code would tend to capture y, hence causing an unintended allocation. You can take advantage of the const and static keywords to prevent this unnecessary allocation, as shown in the code snippet given below. const int y = 1; MyMethod(static x => x + y); To avoid unnecessary and wasteful memory allocation, we can use the static keyword on the lambda and the const keyword on the variable or object that we do not want to be captured. Note that a static anonymous function cannot access locals, parameters, or “this” instances from the enclosing scope, but they can reference static members as well as constant definitions from the enclosing scope (see Microsoft’s documentation). The section that follows illustrates static anonymous functions in more detail. What are static anonymous methods? Static anonymous functions or methods are an improvement to anonymous functions in C# 9. You can now use the static keyword to create static anonymous functions. A static modifier when applied to a lambda or anonymous function is known as a static anonymous function. A static anonymous method can reference static members and also reference constant objects from the enclosing scope. It should be noted that a static anonymous method is incapable of capturing state from the enclosing scope. What this means is that locals, parameters, and “this” instances pertaining to the enclosing scope are not accessible from within a static anonymous function. A non-static local method is capable of capturing state information from the enclosing static anonymous method but it cannot capture state outside the enclosing static anonymous function. Static anonymous method example in C# 9 Now refer to the following code snippet. public class Demo { private string formattedText = "{0} It was developed by Microsoft's Anders Hejlsberg in the year 2000."; void DisplayText(Func<string, string> func) { Console.WriteLine(func("C# is a popular programming language.")); } public void Display() { DisplayText(text => string.Format(formattedText, text)); Console.Read(); } } class Program { static void Main(string[] args) { new Demo().Display(); Console.Read(); } } Refer to the Demo class in the preceding code example. The variable formattedText will be captured by the anonymous method named DisplayText, which in turn would cause memory allocation that you might not have intended. When you execute the above program, the output would display in the console window as shown in Figure 1 below. IDG Figure 1. To disallow the allocation, you can use the const keyword on the formattedText variable and the modifier static on the lambda function as shown in the code snippet that follows. public class Demo { private const string formattedText = "{0} It was developed by Microsoft's Anders Hejlsberg in the year 2000."; void DisplayText(Func<string, string> func) { Console.WriteLine(func("C# is a popular programming language.")); } public void Display() { DisplayText(static text => string.Format(formattedText, text)); Console.Read(); } } And that’s it! There is absolutely no allocation and that’s exactly what we wanted. The ability to use the static modifier on a lambda or an anonymous method is a feature newly added in C# 9. When you add the static modifier to a lambda or an anonymous method, the lambda or anonymous method is said to be a static anonymous function. You can take advantage of the static modifier on a lambda or an anonymous method to ensure that you don’t capture locals or instance state from the enclosing context unintentionally. This is particularly helpful for improving the application’s performance. How to do more in C#: How to work with record types in C# How to use implicit and explicit operators in C# Singleton vs. static classes in C# How to log data to the Windows Event Log in C# How to use ArrayPool and MemoryPool in C# How to use the Buffer class in C# How to use HashSet in C# How to use named and optional parameters in C# How to benchmark C# code using BenchmarkDotNet How to use fluent interfaces and method chaining in C# How to unit test static methods in C# How to refactor God objects in C# How to use ValueTask in C# How to use immutability in C# How to use const, readonly, and static in C# How to use data annotations in C# How to work with GUIDs in C# 8 When to use an abstract class vs. interface in C# Related content feature What is Rust? Safe, fast, and easy software development Unlike most programming languages, Rust doesn't make you choose between speed, safety, and ease of use. Find out how Rust delivers better code with fewer compromises, and a few downsides to consider before learning Rust. By Serdar Yegulalp Nov 20, 2024 11 mins Rust Programming Languages Software Development how-to Kotlin for Java developers: Classes and coroutines Kotlin was designed to bring more flexibility and flow to programming in the JVM. Here's an in-depth look at how Kotlin makes working with classes and objects easier and introduces coroutines to modernize concurrency. By Matthew Tyson Nov 20, 2024 9 mins Java Kotlin Programming Languages analysis Azure AI Foundry tools for changes in AI applications Microsoft’s launch of Azure AI Foundry at Ignite 2024 signals a welcome shift from chatbots to agents and to using AI for business process automation. By Simon Bisson Nov 20, 2024 7 mins Microsoft Azure Generative AI Development Tools news Microsoft unveils imaging APIs for Windows Copilot Runtime Generative AI-backed APIs will allow developers to build image super resolution, image segmentation, object erase, and OCR capabilities into Windows applications. By Paul Krill Nov 19, 2024 2 mins Generative AI APIs Development Libraries and Frameworks Resources Videos