In the process of refactoring some legacy code at work and part of it is to convert an instance of List<Action> to List<Func<Task>>. Elsewhere in the codebase, there are several instances of something along the lines of this:
entity.Tasks.Add(() =>
{
_service.Process(operation)
}
The above would work fine when the Tasks property was List<Action>, but gives errors when turned into List<Func<Task>> with no obvious way to fix it.
I know next to nothing about Func, Task, Action, asynchronous/synchronous programming, particularly in C#. Any help provided is immensely appreciated or even just a referral to information where I could find the information needed to solve this myself.
CodePudding user response:
A quick primer...
List<Action> says: I'm a list that accepts a method with no input parameters and returns void when invoked.
List<Func<Task>> says: I'm a list that accepts a method with no input parameters and returns a Task when invoked.
Note: I'm using the term "method" to represent a named method, delegate, lambda, etc...
For your case, entity.Tasks was originally defined as List<Action>; but is now defined as List<Func<Task>>.
Given the case where you need to take the legacy methods which return no value (void), you could create a shimming method which returns a task after completing the Action from the original method.
For Example...
static Task Shim( Action action )
{
action();
return Task.CompletedTask;
}
// the above will wrap a method that does not return a value such as:
static void DoWork( string str )
{
Debug.WriteLine( str );
}
You can now use the Shim to add to your new collection type. For example...
var list = new List<Func<Task>>();
// add the Shim to the list
list.Add( () => Shim( () => DoWork( "I'm a shim" ) ));
In your use case, it will look something like this:
entity.Tasks.Add(() =>
{
return Shim( () => _service.Process(operation) );
}
// or a bit more shorthanded:
entity.Tasks.Add( () => Shim( () => _service.Process(operation) ));
As pointed out in the comments, the Shim path is less than ideal since the new version really should be wrapped in a Task to be more inline with how Tasks and Exceptions get wrapped up.
Here's an example of wrapping the legacy code into the new version without any shims:
entity.Tasks.Add( () => Task.Run( () => _service.Process(operation) ));
CodePudding user response:
Actions are your void methods that don't return a response. Your tasks collection is expecting a returned task. You can wrap the _service.Process(operation) with a task and within the task, run the _service.Process, then return something like
return Task.FromResult(false);
