0

Take a look at this code:

public async Task<int> GetResult(string param1)
{
    if(param1 == "abc")
       return _knownResult;
    else
       return await LongDatabaseCall();
}

Given that LogDatabaseCall will return a Task<int>, which might be saved into _knownResult, what should be the type of _knownResultTask<int> or ValueTask<int>, performance-wise?

cassandrad
  • 3,412
  • 26
  • 50
Leonardo
  • 10,737
  • 10
  • 62
  • 155
  • what should the type of `_knownResult`? It can only be `int`. `ValueTask.AsTask` is not a type. It's a method. – Sweeper Jun 25 '21 at 03:08
  • 2
    Your method is async, so C# will deal with the lifecycle of the returned `Task`. If your method was not async, you would `return Task.FromResult(...)`. – Jeremy Lakeman Jun 25 '21 at 03:11
  • Adding to the above comment, you would also place any *local* exception on the task and conform to the async and await pattern with `Task.FromException` if returning a raw task – TheGeneral Jun 25 '21 at 03:21
  • The type of `_knownResult` _must_ be an `int`, or something implicitly convertible to an `int`, because that's the value of the async method's result, i.e. it's a `Task`. More generally, async methods aren't magic; they follow the same basic rules as any other method when it comes to matching the type of the expression in your `return` statement with the return type of the method. It's just that in an async method, the return type is wrapped in a `Task`, instead of being declared directly. – Peter Duniho Jun 25 '21 at 05:05
  • I edited the question, bringing new light into the issue at hand, please check Edit 1 – Leonardo Jun 25 '21 at 13:12
  • 1
    Hi Leonardo. I don't see how the added text of the [2nd revision](https://stackoverflow.com/revisions/68124928/2) is relevant with the original question. The question originally looked like a puzzle, with an easy answer: `_knownResult` = `int`. The revised question asks about the difference between two (or more) options, regarding efficiency and performance. But what are the options? This question is purely presented IMHO. My suggestion is to just delete it, and post a new better/clearer question. – Theodor Zoulias Jun 25 '21 at 15:25
  • The question has a simple answer, considering the part `The main issue here is regarding allocation and performance`. It's not a duplicated and linked question doesn't answer this question. – cassandrad Jun 25 '21 at 22:52
  • _"considering the part The main issue here is regarding allocation and performance"_ -- changing the question after it's been answered or closed as a duplicate is a violation of the site guidelines. If you have a different question **post it as a new question**. [Chameleon questions aren't allowed](https://meta.stackexchange.com/questions/286803/change-to-question-invalidates-my-answer-what-to-do). I have rolled back your question to the original one you asked. – Peter Duniho Jun 26 '21 at 02:11
  • 1
    @PeterDuniho I'm not sure it was a good idea to revert the post in this particular situation as now we have an answer that refers to the version that you reverted. In my opinion, that post had potential to be improved with comments (and OP's edits in accordance) instead of closing or reversion. – cassandrad Jun 26 '21 at 17:35
  • @cassandrad: _"now we have an answer that refers to the version that you reverted"_ -- I'm not worried about that at all. The edit the OP made explicitly showed itself to be introducing a whole new question; anyone who exacerbates the situation by a) reopening a post that shouldn't have been reopened, and b) posting an answer to the _new_ question that obviously should have been posted as a separate question, deserves whatever confusion surrounding their answer they get. ... – Peter Duniho Jun 26 '21 at 17:41
  • ... The fact is, even the added question didn't really deserve an answer; it showed no evidence of research, and has also already been answered here. The Q&A [Why would one use Task over ValueTask in C#?](https://stackoverflow.com/questions/43000520/why-would-one-use-taskt-over-valuetaskt-in-c) addresses that adequately as well. – Peter Duniho Jun 26 '21 at 17:41

3 Answers3

2

The main issue here is regarding allocation and performance.

That's almost never the main issue, actually.

When determining whether you should use Task<T> or ValueTask<T>, the main issue is one of developer training: if everyone on your team is familiar with the pitfalls of ValueTask<T>, then I'd recommend that. However, if not all the coders are familiar with ValueTask<T> (which seems to be true in the general case right now), then I'd recommend Task<T>.

The performance aspects are almost always immaterial.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • This answer is really unexpected. I would agree that performance would not play a key role in OP's example(assuming all the info provided), but isn't the whole idea of creating `ValueTask` was to improve performance and reduce allocations? That confuses. – cassandrad Jun 26 '21 at 17:32
  • 3
    @cassandrad: Yes, `ValueTask` improves performance and in some cases reduces allocations, which are seldom detectable except in extreme hot paths. It also creates a cognitive burden for code maintainers. If they are not prepared to handle this burden, then the (most likely undetectably small) performance benefits are not worth the eventual bugs that will occur. – Stephen Cleary Jun 26 '21 at 18:43
0

If you know result already, it means that there is no IO call or required to wait but other part of your method required await.

For clarity I assume that you want to return value 1 for first condition.

// 1. If knownresult is type of Task<int> then   

   public async Task<int> GetResult(string param1)
   {
    if(param1 == "abc")
       return await knownResult;
    else
       return await LongDatabaseCall();
   }
  1. If knownResult is int then (no await)

    public async Task<int> GetResult(string param1)
     {
         if(param1 == "abc")
            return knownResult;
         else
            return await LongDatabaseCall();
     }
    
dotnetstep
  • 17,065
  • 5
  • 54
  • 72
  • 4
    The question asks _"what should the type of _knownResult [be]?"_. This answer doesn't make any attempt at all to answer that question. Nowhere do you discuss what the type of that variable _should_ be, and yet that's exactly what the question asks. – Peter Duniho Jun 25 '21 at 05:06
  • @PeterDuniho if you look at carefully I explained two things like if knownresult is Task type then how can it handle and how it is when it just int. – dotnetstep Jun 25 '21 at 14:30
  • 1
    I didn't have to look carefully to notice those two things. They are clear. So? Neither of those two things do anything to answer the question. – Peter Duniho Jun 25 '21 at 16:20
-3

You can use Task.FromResult.

return Task.FromResult(knownResult);
David Jones
  • 2,879
  • 2
  • 18
  • 23