ZetCode

C# closure

last modified September 15, 2021

C# closure tutorial defines closures and shows how to use them.

Note: The definition of closures may vary a bit in other programming languages.

A closure is an anonymous delegate which maintains access to free variables outside the definition of the block. It can still refer to the variables after the method has finished executing.

var limit = 0;
Predicate<int> greaterThan = e => e > limit;

We have an anonymous lambda expression that refers to the limit variable, even thought it vas not declared in the block or passed as a parameter.

C# closure example

The following is a simple closure example.

Program.cs
using System;
using System.Linq;

var c = CreateCounter();

Console.WriteLine(c());
Console.WriteLine(c());
Console.WriteLine(c());
Console.WriteLine(c());
Console.WriteLine(c());

Func<int> CreateCounter()
{
    int c = 0;
    return () => c = c + 1;
}

The CreateCounter is called several times; after each call, the state (value of c) is retained.

$ dotnet run
1
2
3
4
5

C# closure example II

Closures are often used in LINQ code.

Program.cs
using System;
using System.Linq;

var vals = new int[] {-1, -2, 0, 1, 5, 3};

var limit = 0;
Func<int, bool> greaterThan = e => e > limit;

var res = vals.Where(greaterThan);

foreach (var e in res)
{
    Console.WriteLine(e);
}

In the example, we define a filter delegate. The limit variable that is used in the predicate is a free variable defined outside of the predicate definition.

$ dotnet run 
1
3
5 

C# closure example III

We use a closure in the iterator example.

Program.cs
using System;
using System.Collections.Generic;

var words = new List<string> { "sky", "cloud", "rock", "war", "web" };
var it = CreateIterator(words);

string e;

while ((e = it()) != null)
{
    Console.WriteLine(e);
}

Iterator<T> CreateIterator<T>(IList<T> data) where T : class
{
    var i = 0;
    return delegate { return (i < data.Count) ? data[i++] : null; };
}

public delegate T Iterator<T>() where T : class;

We have a generic iterator. In order for the iterator to work, we must retain the state of the increment variable.

In this tutorial we have worked with closures in C#.

Read C# tutorial or list all C# tutorials.