C# Anonymous Methods
An anonymous method is a method without a name. You define it inline using the delegate keyword, and you assign it directly to a delegate variable. Anonymous methods are an older feature that predates lambda expressions, but you still encounter them in existing codebases.
What Is an Anonymous Method?
Normally, a method has a name and lives in a class. An anonymous method skips the name and exists only at the point where it is defined.
┌────────────────────────────────────────────────────────────┐
│ NAMED vs ANONYMOUS METHOD │
├────────────────────────────────────────────────────────────┤
│ │
│ Named Method: │
│ void Greet(string name) │
│ { │
│ Console.WriteLine("Hello, " + name); │
│ } │
│ // Call it anywhere by name: Greet("Alice"); │
│ │
│ Anonymous Method: │
│ delegate(string name) │
│ { │
│ Console.WriteLine("Hello, " + name); │
│ } │
│ // No name — attached to a delegate variable │
│ │
└────────────────────────────────────────────────────────────┘
Syntax
// Declare a delegate type:
delegate void Greet(string name);
// Assign an anonymous method:
Greet greetUser = delegate(string name)
{
Console.WriteLine("Hello, " + name + "!");
};
// Call it:
greetUser("Alice"); // Hello, Alice!
greetUser("Bob"); // Hello, Bob!
Anonymous Method Without Parameters
delegate void SimpleAction();
SimpleAction action = delegate()
{
Console.WriteLine("Action executed!");
};
action(); // Action executed!
Using Built-In Delegate Types
Instead of declaring your own delegate type, use the built-in Action and Func types.
With Action (no return value)
Action<int, int> showSum = delegate(int a, int b)
{
Console.WriteLine("Sum = " + (a + b));
};
showSum(5, 3); // Sum = 8
With Func (returns a value)
Func<int, int, int> multiply = delegate(int a, int b)
{
return a * b;
};
Console.WriteLine(multiply(4, 6)); // 24
Anonymous Methods Capture Variables
Like lambdas, anonymous methods can capture variables from the surrounding scope. The captured variable is accessible inside the method body.
int baseScore = 10;
Func<int, int> addBase = delegate(int bonus)
{
return baseScore + bonus; // captures baseScore
};
Console.WriteLine(addBase(5)); // 15
Console.WriteLine(addBase(20)); // 30
baseScore = 50; // change the captured variable
Console.WriteLine(addBase(5)); // 55 ← uses new value
Variable Capture Diagram
┌──────────────────────────────────────────────────────────────┐
│ int baseScore = 10; ← outer variable │
│ │
│ Func<int,int> addBase = delegate(int bonus) │
│ { │
│ return baseScore + bonus; ← captures baseScore │
│ }; │
│ │
│ The anonymous method holds a reference to baseScore, │
│ not a copy — so changes to baseScore are reflected. │
└──────────────────────────────────────────────────────────────┘
Anonymous Methods as Event Handlers
Anonymous methods are commonly used to attach short event handlers without creating a separate named method.
using System;
using System.Windows.Forms;
Button btn = new Button();
btn.Text = "Click Me";
// Anonymous method as event handler:
btn.Click += delegate(object sender, EventArgs e)
{
Console.WriteLine("Button was clicked!");
};
Before lambda expressions existed, this was the standard way to write inline event handlers in C#.
Anonymous Method vs Lambda Expression
┌──────────────────────────────────┬──────────────────────────────────┐
│ Anonymous Method │ Lambda Expression │
├──────────────────────────────────┼──────────────────────────────────┤
│ Uses delegate keyword │ Uses => operator │
├──────────────────────────────────┼──────────────────────────────────┤
│ Always uses a block body {} │ Can use single expression │
├──────────────────────────────────┼──────────────────────────────────┤
│ delegate(int x) { return x+1; } │ x => x + 1 │
├──────────────────────────────────┼──────────────────────────────────┤
│ Introduced in C# 2.0 │ Introduced in C# 3.0 │
├──────────────────────────────────┼──────────────────────────────────┤
│ More verbose │ Shorter and cleaner │
├──────────────────────────────────┼──────────────────────────────────┤
│ Can omit parameter list │ Always lists parameters │
└──────────────────────────────────┴──────────────────────────────────┘
Side-by-Side Code Comparison
// Anonymous method:
Func<int, int> doubleA = delegate(int x)
{
return x * 2;
};
// Equivalent lambda:
Func<int, int> doubleB = x => x * 2;
// Both produce the same result:
Console.WriteLine(doubleA(5)); // 10
Console.WriteLine(doubleB(5)); // 10
Omitting the Parameter List
Anonymous methods have one unique feature: if you do not need the parameters, you can omit the parameter list entirely. Lambda expressions cannot do this.
Action<string> ignoreInput = delegate
{
Console.WriteLine("I ignore my parameter.");
};
ignoreInput("anything"); // I ignore my parameter.
// This omits the parameter list — valid only for anonymous methods
// The lambda equivalent must include (string s) or _ => ...
Real-World Example: Sorting
List<string> names = new List<string>() { "Carol", "Alice", "Bob", "Dave" };
// Sort using an anonymous method:
names.Sort(delegate(string a, string b)
{
return string.Compare(a, b); // alphabetical
});
foreach (string name in names)
{
Console.WriteLine(name);
}
// Alice
// Bob
// Carol
// Dave
Quick Summary
┌──────────────────────────────────────────────────────────────┐
│ Anonymous method syntax: │
│ delegate(params) { body } │
│ │
│ Key points: │
│ • No name — inline definition only │
│ • Captures outer variables (closure) │
│ • Used with Action, Func, or custom delegates │
│ • Can omit parameter list (unique to anonymous methods) │
│ • Lambda expressions replaced most anonymous method uses │
│ • Still found in older C# code — good to recognize │
└──────────────────────────────────────────────────────────────┘
Anonymous methods laid the foundation for the cleaner lambda expressions that followed. Understanding them helps you read older C# code and appreciate why lambdas became so popular. In new code, prefer lambda expressions — they are shorter and equally powerful.
