PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, October 26, 2022

[FIXED] What are the best practices for implementing a Run method from an interface where synchronous and asynchronous methods are possible?

 October 26, 2022     .net-core, c#, oop     No comments   

Issue

I want to implement an interface that has a Run method:

public interface IRunner
{
    bool Run();
}

But the issue I am facing is that some Run functions should be synchronous and some should be asynchronous. One solution would be to implement two interfaces:

public interface IRunner
{
    bool Run();
}

public interface IRunnerAsync
{
  Task<bool> RunAsync();
}

But the issue here is, that if I have, say, a list of objects implementing these interfaces, I will have to always make a check of what type each object is before calling the method, which feels hacky. What would be best practices to implement interfaces like these?


Solution

Perhaps just have the async version, and accept that some callers may implement it internally in a synchronous fashion; they can do this locally and just return the true/false as a wrapped task via Task.FromResult, noting that (at least in current frameworks) the runtime will special-case the bool case, and avoid allocating multiple tasks internally (the details aren't important). Your consumption code can just await an already-completed synchronous result, and everything will keep working. In some very specific scenarios (usually in library code), it may be beneficial for your consumption code to explicitly test for synchronously-completed results, and optimize away some of the async overheads.

In a more general Task<T> scenario, where you don't want the synchronous implementations to have to allocate, consider switching to ValueTask<T> instead; with that API, synchronous implementations can return a new ValueTask<TheType>(value) without allocating, and asynchronous versions can either wrap a Task<T>, or can simply declare themselves as async ValueTask<T> Whatever() and let the compiler worry about the details. There is also a third way of implementing ValueTask<T>, for niche async low-allocation scenarios, but: that's probably overkill here. One caveat with ValueTask[<T>]: a value-task should only be awaited once (or rather: the outcome should only be retrieved once).



Answered By - Marc Gravell
Answer Checked By - Pedro (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing