C# Local Functions are an interesting feature released with C# 7.0. C# local functions are methods declared in another method and run in the context of that method. They are methods that are used only by one other method and help to keep each method small and focused.
In this post we explore C# Local functions and learn how best to make use of them in .net core applications.
What are local functions in C#
Essentially C# local functions allow the specification of a functions within the body of another method or function and only run within the context of that method.
C# Local Functions are designed to be methods that are used by only one other method to help keep each method small and focused in order to reduce class bloat. Local functions can be defined in the body of any method, constructor or property.
Inner Functions in Python
The Python Programming language also has the concept of
In C# 6.0 developers could replicate similar functionality in making use of
Func<T> delegate inside of a method.
In c# 7.0 we can now replace this implementation as follows
Why Local Functions in C#
There are several advantages to local functions
You use local functions to protect them from anything happening outside of the function, meaning that they are hidden from the global scope
Keeping it DRY
When writing functions you may possibly want to use the same block of code in numerous places. However, that block of code will only make sense in the context of the function, and will not be used anywhere else in your application.
It’s not worth the administrative overhead of extracting that out its own function at the class level. Using a local function you can extract the logic for reuse within the function.
Closure and Factory Functions
This is probably the most important reason to use local functions. Most local functions may be just ordinary functions that merely happened to be nested inside another function.
However, the ideal case for local functions is to do with encapsulation of some behaviour and pass it around like any other object, and still have access to the context in which they were first declared.
What’s a closure
A closure simply causes the inner function to remember the state of its environment when called. The closure closes the local variable on the stack and this stays around after the stack creation has finished executing.
The use of closures and factory functions is the most common, and powerful, use for local functions. In most cases, when you see a decorated function, the decorator is a factory function which takes a function as argument, and returns a new function which includes the old function inside the closure.
C# Local Functions in action
We’ll create contrived example of local functions. Just to illustrate their use.
A console application that generates some form of random hero name for a user.
There is nothing really complicated about this code. However, it does prove a couple of really important concepts of Local Functions.
- Local Functions don’t have to have a return type eg.
- Local Functions can have return types
- Local functions can call each other
- Local functions can accept parameters
Lets quickly add some additional logic, to cope with a user not liking his given Hero Name. We’re not going win any clean code points here, but I just wanted to highlight some important functionality to do with variables.
I just want to highlight here that if you declare a variable within the root function, it is accessible and writable by the nested functions.
Run the application and it will work.
The issue with the code here is that no support team will thank you for writing this spaghetti code!
We’ve utilised some great functionality in C#, but have only leveraged it to create a support nightmare.
Lets refactor the code and explore what else we can do with local functions.
We’ll make use of events and even look at creating a
self cleaning delegate , which previously required a lot of code trickery, but now is a relatively trivial task in C#
Important considerations of C# local functions
- Scope of Local functions are only within the method they are defined and they should not contain system-wide logic.
- Local functions are not visible to other classes
- They are unit tested with methods that own them.
- Use local functions only if treally needed.
- over-use of local functions may lead to long methods that are hard to test.
It may not be immediately apparent in the above contrived examples, but local functions are extremely useful in solving computer science algorithm challenges.
Although it may be possible to make use of Lambda expression to do similar types of tasks there are a number of reasons to prefer using local functions instead of defining and calling lambda expressions.
For more info on this check out the Microsoft article – Local functions compared to Lambda expressions
Bill Wagner blog post : C# 7 Feature Proposal: Local Functions is also worth reading for further background on this great language feature.