Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
Ask Question
I'm trying to make a method that accepts another method, and returns the value that the inner method returns, if that inner method isn't void. I'd like to do it without differentiating between
Func<>
and
Action<>
.
Essentially, I want the wrapped method to behave the exact same way as the unwrapped method, plus some functionality provided by the wrapper. The goal is simple enough, but it's hard to wrap my head around the implementation.
public int ReturnsInteger() {
Console.WriteLine("I return 42");
return 42;
public static T WrapperMethod(Func<T> someMethod) {
Console.WriteLine("Wrap start");
var result = someMethod();
Console.WriteLine("Wrap end");
return result;
private static void Main() {
var X = WrapperMethod(()=>ReturnsInt());
Console.WriteLine("X = " + X);
// Wrap start
// I return 42
// Wrap end
// X = 42
public void ReturnsNothing() {
Console.WriteLine("I return nothing");
return;
public static T WrapperMethod(Action someMethod) {
Console.WriteLine("Wrap start");
someMethod();
Console.WriteLine("Wrap end");
private static void Main() {
WrapperMethod(()=>ReturnsNothing());
// Wrap start
// I return nothing
// Wrap end
–
–
–
–
–
As noted above, I don't entirely understand the wording of your question. However, the basic scenario seems plain: you want to generically decorate the behavior of unknown methods, handling both methods that return values and those which don't.
Whenever I run into that type of scenario, I address it by writing one wrapper method that has return type void, and then adapting via a lambda a second wrapper method. For example:
T Wrapper<T>(Func<T> func)
T result = default(T);
Wrapper(() => { result = func(); });
return result;
void Wrapper(Action action)
Console.WriteLine("Wrap start");
action();
Console.WriteLine("Wrap end");
This way I only have to write the wrapper logic once. There's some overhead with the Func<T> version having to create a new delegate instance and capture a local variable, but at least when I've had to do this sort of thing, the wrapper logic and wrapped logic is complex enough that the overhead of the lambda is inconsequential.
–
–
–
I would try to take away the fundamental language difference of a void returning method by actually giving the method something to return.
By implementing a Unit type, that is just a single value struct, then you can transform Action into Func<Unit>. This is effectively just using the adapter pattern.
Now you're just dealing with one kind of delegate in the form of Func<T>. You can then put all of the hard work into that single Wrapper method.
Try this:
void Main()
var result = Wrapper(DoSomething);
private void DoSomething()
Console.WriteLine("Test.");
T Wrapper<T>(Func<T> func)
Console.WriteLine("Wrap start");
var result = func();
Console.WriteLine("Wrap end");
return result;
Unit Wrapper(Action action)
return Wrapper(() => { action(); return Unit.Default; });
/// <summary>
/// Represents a type with a single value. This type is often used to denote the successful completion of a void-returning method (C#) or a Sub procedure (Visual Basic).
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential, Size = 1)]
public struct Unit : IEquatable<Unit>
public static Unit Default => default(Unit);
public bool Equals(Unit other) => true;
public override bool Equals(object obj) => obj is Unit;
public override int GetHashCode() => 0;
public override string ToString() => "()";
public static bool operator ==(Unit first, Unit second) => true;
public static bool operator !=(Unit first, Unit second) => false;
–
–
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.