Local functions are another very handy feature to be introduced into language if you are into code refactoring. Many a times developers create a very large method and while code review we see lot of places same logic has been repeated and thus think about refactoring it. Problem is that if the logic is required only at multiple places within same method than it’s not a good idea to make it into a separate named method.
Let’s take an example in C# 6 and then we will try to refactor that using various ways and finally with local functions feature in C# 7.0
Here is a simple code that works on array of numbers and calculates sum and subtraction of each number in array
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
int[] numbers = System.Linq.Enumerable.Range(1, 100).ToArray(); //We need to find Sum and Subtract for first 100 natural numbers //Sum var sum = 0; for (int i = 0; i < numbers.Length; i++) { sum = sum + i; } //Subtraction var subtraction = 0; for (int i = 0; i < numbers.Length; i++) { subtraction = subtraction - i; }
Let’s check the refactored version using delegates.
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
//After first level refactoring using delegates Func<int[],Func<long,int,long>, long> aggregator = (nums,action) => { long output = 0; for (int i = 0; i < nums.Length; i++) { output = action(output,i); } return output; }; //Sum var sum2 = aggregator(numbers, (i, j) => i + j); //Subtraction var subtraction2 = aggregator(numbers, (i, j) => i - j);
Delegates are local functions equivalent in C# 6.0 with exception that delegate calls are resolved at runtime this involves a performance hit.
While refactoring we need to look at both code quality as well as performance so here comes same example using Local functions syntax in C# 7.0
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
int[] numbers = System.Linq.Enumerable.Range(1, 100).ToArray(); //Sum var sum2 = Aggregator(numbers, (i, j) => i + j);// 1 late binding call .Only one for logic to be passed to aggregator //Subtraction var subtraction2 = Aggregator(numbers, (i, j) => i - j); //With Local functions long Aggregator(int[] nums, Func<long, int, long> action) { long output = 0; for (int i = 0; i < nums.Length; i++) { output = action(output, i); } return output; };
In above example, I have intentionally placed the method definition after the usage. This would have resulted with compile time error with normal variable definitions but local functions are an exception and comes into existence within method scope once declared anywhere inside functions.
You can even return values are Tuples which will again be defined in local scope and can be used before actual declaration as below
var sum2 = Aggregator2(numbers, (i, j) => i + j).output; //Returned Tuple and accessed output value in current scope //With Local functions (long output,int something) Aggregator2(int[] nums2, Func<long, int, long> action2) { long output = 0; for (int i = 0; i < nums2.Length; i++) { output = action2(output, i); } return (output,0); };
All code samples are available at my GitHub profile
I am a corporate trainer and solution architect and have a great team of software professionals. Please contact in case you need our services by sending email to contact@techprocompsoft.com. Here is our company website .