Question
I have several methods with the same parameter types and return values, but they have different names and different implementations. I want to pass one of these methods into another method and have that method call it.
For example, I am trying to do something like this:
public int Method1(string input)
{
// Do something
return 1;
}
public int Method2(string input)
{
// Do something different
return 2;
}
public bool RunTheMethod([method parameter goes here] myMethodName)
{
// Do stuff
int i = myMethodName("My String");
// Do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
This code does not work as written, but it shows what I am trying to achieve. What I do not understand is how to define the parameter type in RunTheMethod so that it can accept a method and invoke it.
Short Answer
By the end of this page, you will understand how C# allows methods to be passed as parameters using delegates. You will learn the modern Func<...> syntax, see how it matches method signatures, and understand how to call the passed method inside another method. You will also see practical examples, common mistakes, and how this pattern is used in real C# codebases.
Concept
In C#, you cannot pass a method by writing a parameter type like "method name". Instead, you pass a delegate.
A delegate is a type that represents a reference to a method with a specific signature.
A method signature includes:
- the parameter types
- the return type
If two methods have the same signature, they can both be assigned to the same delegate type.
For the example in this question, both methods match this signature:
- input:
string - output:
int
That means RunTheMethod should accept something that represents "any method that takes a string and returns an int".
In modern C#, the most common way to do this is with Func<string, int>.
Func<string, int>means:- takes a
string - returns an
int
- takes a
So instead of trying to pass a method name directly, you define the parameter like this:
public bool ()
Mental Model
Think of a delegate like a remote control button.
The RunTheMethod function does not need to know the actual method's name in advance. It only needs a button it can press.
If the button is wired to Method1, pressing it runs Method1.
If the button is wired to Method2, pressing it runs Method2.
What matters is that every button works the same way:
- it accepts one
string - it gives back one
int
So RunTheMethod is not asking for a specific method name. It is asking for anything callable with that shape.
Syntax and Examples
The simplest modern solution uses Func<TInput, TResult>.
using System;
public class Example
{
public int Method1(string input)
{
return input.Length;
}
public int Method2(string input)
{
return input.IndexOf(' ');
}
public bool RunTheMethod(Func<string, int> myMethod)
{
int result = myMethod("My String");
Console.WriteLine(result);
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
}
What this means
Func<string, int>defines a method type.Method1matches that type because it takes a and returns an .
Step by Step Execution
Consider this small example:
using System;
public class Example
{
public int Method1(string input)
{
return input.Length;
}
public bool RunTheMethod(Func<string, int> myMethod)
{
int i = myMethod("My String");
Console.WriteLine(i);
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
}
Step-by-step
-
Test()is called. -
Test()callsRunTheMethod(Method1). -
The method
Method1is passed intoRunTheMethodas a delegate.
Real World Use Cases
Passing methods as parameters is very common in C#.
1. Reusable processing pipelines
You may have a method that handles logging, timing, or validation, and then runs one of several operations.
public int ExecuteWithLogging(Func<string, int> operation, string input)
{
Console.WriteLine("Starting...");
int result = operation(input);
Console.WriteLine("Done.");
return result;
}
2. Sorting and filtering
LINQ uses this idea heavily. You pass logic into methods like Where, Select, and OrderBy.
var shortNames = names.Where(name => name.Length < 5);
The lambda is a function passed as a parameter.
3. Event handling
In UI apps and desktop apps, methods are passed as handlers for clicks, changes, or other events.
4. Retry and error-handling wrappers
You can pass an operation into a generic method that retries on failure.
5. Business rules
An application may pass different calculation methods depending on customer type, pricing mode, or feature flags.
Real Codebase Usage
In real projects, this pattern is often used to separate shared workflow from custom behavior.
Common patterns
- Guard clauses before invoking the method
- Validation of input
- Logging around execution
- Error handling with
try/catch - Configuration-based behavior where one of several methods is chosen dynamically
Example with a guard clause
public bool RunTheMethod(Func<string, int> myMethod)
{
if (myMethod == null)
{
throw new ArgumentNullException(nameof(myMethod));
}
int result = myMethod("My String");
Console.WriteLine(result);
return true;
}
Example with shared workflow
public int RunWithAudit(Func<string, int> operation, string input)
{
Console.WriteLine();
result = operation(input);
Console.WriteLine();
result;
}
Common Mistakes
1. Passing the result instead of the method
Broken code:
RunTheMethod(Method1("Hello"));
Why it is wrong:
Method1("Hello")executes immediately.- It returns an
int. - But
RunTheMethodexpects a delegate, not anint.
Correct:
RunTheMethod(Method1);
2. Using the wrong delegate type
Broken code:
public bool RunTheMethod(Action<string> myMethod)
Why it is wrong:
Action<string>means the method takes astringand returnsvoid.- Your methods return
int, so this does not match.
Correct:
Comparisons
| Approach | What it is | Best for | Example |
|---|---|---|---|
Func<string, int> | Built-in generic delegate | Most common cases | RunTheMethod(Func<string, int> method) |
| Custom delegate | Named delegate type | When you want clearer domain meaning | delegate int StringOperation(string input); |
| Lambda expression | Inline function | Short one-off behavior | RunTheMethod(s => s.Length) |
Action<string> | Delegate with no return value | Methods that return void | Action<string> |
Cheat Sheet
// Method signature to match
int SomeMethod(string input)
// Receive a method as a parameter
public bool RunTheMethod(Func<string, int> myMethod)
{
int result = myMethod("My String");
return true;
}
// Pass a method
RunTheMethod(Method1);
// Pass a lambda instead
RunTheMethod(s => s.Length);
// Custom delegate alternative
public delegate int StringOperation(string input);
Rules
- The method signature must match exactly.
- Use
Func<...>for methods that return a value.
FAQ
How do you pass a method as a parameter in C#?
Use a delegate type such as Func or Action. For a method that takes a string and returns an int, use Func<string, int>.
What is a delegate in C#?
A delegate is a type that can store a reference to a method with a specific signature.
When should I use Func instead of Action?
Use Func when the method returns a value. Use Action when the method returns void.
Can I pass a lambda instead of a named method?
Yes. For example:
RunTheMethod(s => s.Length);
Does the method signature need to match exactly?
Yes. The parameter types and return type must match the delegate type.
Can instance methods be passed as parameters?
Yes, as long as you pass them from an object instance when needed.
Is Func better than creating a custom delegate?
Usually yes for simple cases. A custom delegate is useful when a named delegate makes the code clearer.
Mini Project
Description
Build a small text-processing utility where one method handles the common workflow and accepts different string-processing methods as parameters. This demonstrates how delegates let you reuse one execution pipeline while changing the behavior that runs inside it.
Goal
Create a program that can run different string-to-int operations through a shared method.
Requirements
- Create at least two methods that take a
stringand return anint. - Write a
RunOperationmethod that accepts one of those methods as a parameter. - Call
RunOperationwith each method. - Print the result of each operation.
- Add a null check before invoking the passed method.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Array Initialization Syntaxes Explained
Learn all common C# array initialization syntaxes with examples, rules, comparisons, and mistakes beginners often make.