C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
61: Local Functions
What exactly is a local function, and when should I actually use one?
Think of a local function as a method that lives entirely inside another method. You've probably written a lot of private helper methods in your classes to keep your main logic clean, but sometimes a helper is so specific that it only makes sense within the context of one single method. When that happens, making it a class-level private method just clutters up your class API.
I usually reach for a local function when I have a repetitive task—like a complex validation check or a specific data transformation—that doesn't belong anywhere else. Here is a quick look at how that looks in a real scenario: processing a user's order.
public void ProcessOrder(Order order)
{
// The local function is defined right here inside the method
bool IsValid(Order o)
{
return o.Items.Any() && !string.IsNullOrWhiteSpace(o.ShippingAddress);
}
if (!IsValid(order))
{
throw new InvalidOperationException("Order is missing items or address.");
}
// ... proceed with processing ...
}
Why not just use a private method or a lambda expression instead?
This is the question I get most often. You could definitely use a private method, but then any other method in your class can call it. By using a local function, you're enforcing a strict scope. It's the ultimate form of encapsulation.
Now, what about lambdas (like Func<T, TResult>)? Local functions are generally preferred over lambdas for a few reasons. First, they are more performant because they don't always require a heap allocation for a delegate. Second, they support things lambdas can't do easily, like optional parameters or generics. Honestly, they just feel more like "real" methods while staying tucked away where they belong.
Can a local function "see" the variables in the parent method?
Yes, and this is where they really shine. Local functions can capture local variables from the enclosing scope. This means you don't have to pass a dozen arguments into your helper function; it just knows about the variables already present in the method.
Take a look at this example. I'm calculating a total price, and the local function needs access to the taxRate defined in the main method:
public decimal CalculateTotal(decimal subtotal, string region)
{
decimal taxRate = region == "NY" ? 0.08m : 0.05m;
// This local function "captures" the taxRate variable from above
decimal ApplyTax(decimal amount) => amount * (1 + taxRate);
decimal shipping = 10.00m;
return ApplyTax(subtotal) + shipping;
}
If this were a private class method, I'd have to pass taxRate as a parameter every single time I called it. Local functions cut out that noise.
Does it matter where I define the function inside the method?
Surprisingly, no. You can define a local function at the top of your method, or you can tuck it all the way at the bottom. C# handles this via "hoisting," meaning the compiler finds the function regardless of where it's declared within that block.
I personally prefer putting them at the bottom. I like to keep the "happy path" of my logic—the primary sequence of events—at the top of the method so that someone reading my code doesn't have to scroll past three helper functions just to see what the method actually does.
📋 Practical Task
Build a Local-Function Based Discount Validator
You are building a checkout system. Your task is to create a method called ApplyDiscount that takes a decimal currentTotal and a string couponCode.
Inside this method, implement a local function called IsCouponValid. This local function should:
- Return
trueif thecouponCodeis "SAVE10" or "WELCOME20". - Return
falseotherwise.
The main ApplyDiscount method should use this local function to determine if it should subtract a discount amount from the total. If the coupon is "SAVE10", subtract 10%; if it's "WELCOME20", subtract 20%. If it's invalid, return the original total.
Constraint: The IsCouponValid logic must be contained within a local function, not a separate private method or a lambda.
There are no comments for now.