Click here to Skip to main content
15,884,298 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I have a class that has a function that runs the supplied delegate, which is of type Func<T>, as shown in the following code.

public static class FunctionRunner
{
	public static int RunSuppliedFunction( Func<int> aFunctionReturningInt ) => aFunctionReturningInt();
}


public int CallingMethod()
{
	return FunctionRunner.RunSuppliedFunction( () => 42 );
}


This compiles fine.

What if I wish to change the type of the delegate to be asynchronous, which I think means its type will then be Func<Task<int>> (but I may be wrong about even this)?

What is the syntax I need to get this to work?

What I have tried:

I seem to have tried everything. The compiler is doing its best to tell me what I am doing wrong but I am having a blonde day and cannot figure it out. (Not PC to say 'blonde day' but as I have blonde hair, I think I can get away with it.)

This is as far as I have got:

public static class FunctionRunner
{
    public static int RunSuppliedFunction( Func<int> functionReturningInt ) => functionReturningInt();
}

private async Task<int> SomeFunction()
{
    await Task.Delay( 100 );
    return 42;
}

public async Task<int> CallingMethod()
{
    return await FunctionRunner.RunSuppliedFunction( SomeFunction );
}


Which gives a compiler message: 'SomeFunction() has the wrong return type.'
Posted
Updated 26-Aug-20 2:10am
v2

The return type of an async function will need to be Task<T> or ValueTask<T>, so your delegate type will be either Func<Task<T>> or Func<ValueTask<T>>.

The function runner effectively doesn't care whether or not the function is async - it just calls the function and returns the result. You can make the method generic to allow any return type:
C#
public static class FunctionRunner
{
    public static T RunSuppliedFunction<T>(Func<T> theFunction) => theFunction();
}
If the delegate returns Task<T> or ValueTask<T>, the calling method will either need to return the result directly, or be marked as async and await the result:
C#
private Task<int> theAsyncFunction = ...;

// Either:
public Task<int> CallingMethod() => FunctionRunner.RunSuppliedFunction(theAsyncFunction);

// Or:
public async Task<int> CallingMethod() => await FunctionRunner.RunSuppliedFunction(theAsyncFunction);
TBH, I don't think that the FunctionRunner class adds anything here - you could just call the Func<> directly.
C#
// Either:
public Task<int> CallingMethod() => theAsyncFunction();

// Or:
public async Task<int> CallingMethod() => await theAsyncFunction();

Edit: Based on the updated question, you still need to update the definition of RunSuppliedFunction:
C#
public static class FunctionRunner
{
    public static Task<int> RunSuppliedFunction( Func<Task<int>> functionReturningInt ) => functionReturningInt();
}

private async Task<int> SomeFunction()
{
    await Task.Delay( 100 );
    return 42;
}

public async Task<int> CallingMethod()
{
    return await FunctionRunner.RunSuppliedFunction( SomeFunction );
}
 
Share this answer
 
v2
Comments
Patrick Skelton 26-Aug-20 7:57am    
Thank you for the reply, Richard. I have improved my question to be a bit closer to what I am actually trying to do. I tried to follow your code but still get the error mentioned in the question. (You are right that, in the example I give, the FunctionRunner adds nothing. In the real code, it receives three delegates and decides which one to run depending upon certain conditions. I chopped it down to give the shortest possible code example.)
With the helpful nudge from @Richard Deeming, I have got the code compiling like this (which also moves a step closer to showing what the point of all this is):

public static class FunctionRunner
{
    public static async Task<int> RunSuppliedFunction( bool whichFunction, Func<Task<int>> functionA, Func<Task<int>> functionB ) =>
        ( whichFunction) ? await functionA() : await functionB();
}

public async Task<int> CallingMethod()
{
    bool whichFunction = true;
    return await FunctionRunner.RunSuppliedFunction
    (
        whichFunction,
        async () =>
        {
            await Task.Delay( 100 );
            return 42;
        },
        async () =>
        {
            await Task.Delay( 100 );
            return 43;
        }
    );
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900