Action as Func in C#
Asked Answered
A

3

13

I have a parametric method that takes a Func as an argument

SomeType SomeMethod<T>( Func<T, T> f ) {...}

I would like to pass an Action without having to overload the method. But this takes to the problem, how do you represent and Action as a Func? I tried

Func<void, void>

but its not valid.

Astraea answered 30/5, 2014 at 17:40 Comment(5)
you can't.......Remembrancer
And never will be, Func does not allow void return types (because of that the existance of Action delegate). You can always wrap your Action into a lambda (o) => { ExecuteAction(); return true; }Ostraw
Very good question, and also one that does not have a satisfactory answer in C#. You are running into this issue: james-iry.blogspot.com/2009/07/void-vs-unit.htmlEthel
@Ostraw yeah, It's basically what I am doing, but that makes me write an unnecessary return, which is what I am trying to solve.Astraea
If the return isn't necessary why does SomeMethod expect a Func? Surely it's using that return value.Handiwork
P
12

You can create an extension method to wrap an action and return a dummy value:

public static class ActionExtensions
{
    public static Func<T, T> ToFunc<T>(this Action<T> act)
    {
        return a => { act(a); return default(T) /*or a*/; };
    }
}

Action<?> act = ...;
SomeMethod(act.ToFunc());

It might be clearer if you create your own Unit type instead of using object and returning null.

Penetrating answered 30/5, 2014 at 17:48 Comment(5)
Never used default, what does it do?Astraea
@CristianGarcia - It returns null for reference types and 'zero' for value types.Penetrating
I get this error: Extension method must be defined in a non-generic static classAstraea
@CristianGarcia - You have to define extension methods in static classes - see update.Penetrating
@CristianGarcia Also, structs are value types that can't be set to 0. The default value of a struct is where all its value properties are set to 0 and its reference properties are set to null. msdn.microsoft.com/en-us/library/aa664475(v=vs.71).aspxRoyo
W
3

.NET Fiddle

What you are looking for is a "statement lambda" msdn.

A statement lambda is when you wrap your expression (right hand side) in curly braces {}. This allows for more than 1 statement to be used. For your specific example, you could do this:

void Main()
{
    Func<bool,bool> f = i => {SomeAction();return true;};
    Console.WriteLine(SomeMethod(f));
}

public T SomeMethod<T>( Func<T, T> f ) 
{
    return f(default(T));
}

public void SomeAction()
{
    Console.WriteLine("called");
}

output

called
True
Waterresistant answered 30/5, 2014 at 17:56 Comment(0)
S
1

You can't turn an Action into a Func. But you could wrap a call to the Action in a Func. For example, something like:

Action a = new Action<Foo>(f => { whatever });

Foo myFoo = ...;
Foo result = SomeMethod(new Func<Foo, Foo>(f => { a(myFoo); return myFoo; }));

(Don't have Visual Studio up at the moment, but I think you get the idea.)

Systemize answered 30/5, 2014 at 17:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.