C# Func Delegate: Input and Output Types
The Func delegate in C# is a versatile, built-in generic
delegate designed to reference methods that take zero or more parameters
and return a value. This article explains what the Func
delegate is, how it functions in modern .NET development, and the exact
rules for declaring its input and output types using generic type
arguments.
What is the Func Delegate?
The Func delegate is part of the System
namespace and serves as a pre-defined delegate type. Instead of
requiring you to declare custom delegates using the
delegate keyword, .NET provides Func to handle
method references that produce a result. If you need a method that
performs an operation and returns a value—such as calculating a sum,
formatting a string, or evaluating a boolean condition—you use
Func. If your method returns void, C# provides
the Action delegate instead.
Specifying Input and Output Types
To specify the input and output types of a Func
delegate, you pass type arguments inside angle brackets
(< >). The Func delegate can take
anywhere from 0 to 16 input parameters, but it must always have exactly
one return type.
The fundamental rule for the generic type parameters is: the last type argument is always the return (output) type. Any type arguments listed before the final one correspond to the input parameters in their exact order.
Here is the general breakdown:
- Zero input parameters:
Func<TResult>
Takes no inputs and returns a value of typeTResult. - One input parameter:
Func<T, TResult>
Takes one input of typeTand returns a value of typeTResult. - Two input parameters:
Func<T1, T2, TResult>
Takes a first parameter of typeT1, a second parameter of typeT2, and returns a value of typeTResult. - Multiple input parameters (up to 16):
Func<T1, T2, ..., T16, TResult>
Takes up to 16 parameters in sequence, withTResultremaining the final output type.
Practical Examples
1. No Input Parameters, Single Output
// Takes no parameters, returns a string
Func<string> getMessage = () => "Hello, World!";
string message = getMessage(); // Returns "Hello, World!"2. One Input Parameter, Single Output
// Takes an integer, returns an integer
Func<int, int> square = x => x * x;
int result = square(5); // Returns 253. Multiple Input Parameters, Different Output Type
// Takes two integers, returns a boolean
Func<int, int, bool> isGreater = (a, b) => a > b;
bool check = isGreater(10, 5); // Returns true4. Mixed Input Types
// Takes a string and an int, returns a string
Func<string, int, string> repeatText = (text, count) => string.Concat(Enumerable.Repeat(text, count));
string repeated = repeatText("A", 3); // Returns "AAA"By adhering to the rule that the final type parameter represents the return value, you can easily define signatures for LINQ queries, asynchronous callbacks, and higher-order functions throughout C#.