C#
Func
Delegates
Programming
.NET

In C, What is FuncT1, T2, and what is it for?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Func<T1, T2> is a C# generic delegate type, not a C language feature. It represents a method that takes one argument of type T1 and returns a value of type T2, which makes it a convenient standard way to pass behavior around without declaring a custom delegate for every small callback shape.

Read the Type Parameters Correctly

The rule for Func is simple:

  • every type parameter except the last one is an input type
  • the last type parameter is the return type

So Func<int, string> means “a function that takes an int and returns a string.”

csharp
1using System;
2
3Func<int, string> describe = n => $"value={n}";
4Console.WriteLine(describe(42));

That lambda matches the signature exactly: one int goes in, one string comes back.

Why Func Exists

Without Func, you would often end up declaring many tiny delegate types just to pass small pieces of logic around.

These two ideas are equivalent in shape:

csharp
public delegate string Formatter(int value);

and

csharp
Func<int, string>

The built-in form is shorter, familiar to most .NET developers, and heavily used across the framework.

Func Appears Everywhere in LINQ

One of the most common places you see Func is in LINQ, even when you do not write the type explicitly.

csharp
1using System;
2using System.Linq;
3
4var numbers = new[] { 1, 2, 3, 4, 5 };
5
6var evenLabels = numbers
7    .Where(x => x % 2 == 0)
8    .Select(x => $"n={x}");
9
10foreach (var label in evenLabels)
11{
12    Console.WriteLine(label);
13}

Where expects a function from item to bool, and Select expects a function from item to transformed output. The compiler usually infers the Func<...> types from the lambdas.

Pass Behavior into Your Own Methods

Func is especially useful when a method should accept a strategy or calculation.

csharp
1using System;
2
3static int Apply(int input, Func<int, int> operation)
4{
5    return operation(input);
6}
7
8Console.WriteLine(Apply(10, x => x * 2));
9Console.WriteLine(Apply(10, x => x + 7));

This lets the caller choose the behavior without subclassing or writing a switch statement for every variation.

Compare Func, Action, and Predicate

C# has a few related delegate families:

  • 'Func<...> returns a value'
  • 'Action<...> returns nothing'
  • 'Predicate<T> returns bool for one input'
csharp
1using System;
2
3Action<string> log = message => Console.WriteLine(message);
4Predicate<int> isEven = n => n % 2 == 0;
5Func<int, int> square = n => n * n;
6
7log($"isEven(6)={isEven(6)}");
8log($"square(5)={square(5)}");

If you need a result, Func is the standard delegate family.

Func Can Represent Async Work Too

Because Func is just a delegate type, it can also describe methods that return Task.

csharp
1using System;
2using System.Threading.Tasks;
3
4Func<Task<int>> load = async () =>
5{
6    await Task.Delay(50);
7    return 7;
8};
9
10Console.WriteLine(await load());

This pattern appears in retry helpers, lazy initialization, and dependency-injection factories.

Use It Where It Clarifies, Not Everywhere

Func is great for small, generic pieces of behavior. But not every domain concept should be represented as an anonymous delegate. If the operation has real business meaning, a named interface or named method may communicate intent better.

The practical rule is to use Func for convenience while keeping readability first.

Common Pitfalls

  • Reading the type parameters in the wrong order and forgetting the return type is last.
  • Assuming Func<T1, T2> is related to the C language instead of C# delegates.
  • Using Func for every behavior even when a named abstraction would be clearer.
  • Forgetting that captured local state inside lambdas can affect behavior unexpectedly.
  • Confusing Func with Action when no return value is actually needed.

Summary

  • 'Func<T1, T2> is a C# generic delegate for one input and one return value.'
  • All type parameters except the last are inputs; the last is the result type.
  • 'Func is widely used in LINQ, callbacks, and dependency-injection patterns.'
  • Use Action when no value is returned and Predicate<T> for simple boolean tests.
  • 'Func is useful, but named abstractions are sometimes better for domain clarity.'

Course illustration
Course illustration

All Rights Reserved.