C#
C#

help

Root Question Message

thinker227
thinker2278/14/2022
When to use ValueTask?

Despite having used C# for a while I'm... not that familiar with async. I know people sometimes say to sometimes use ValueTask<T> instead of Task<T>, but when should you exactly do this? The extent of my knowledge (and reading the docs) is that ValueTask<T> is like a DU between either a T value or a Task<T>, so is it ideal for situations in which an async method may just return a cached value?
thinker227
thinker2278/14/2022
And since you can use ValueTask<T> as the result of an async method, is the compiler smart enough to generate the appropriate code based on whether such a cached value is used without any async calls being used?
canton7
canton78/14/2022
It's more that it's a cheaper alternative to Task, but more limited
thinker227
thinker2278/14/2022
Mind elaborating?
canton7
canton78/14/2022
It doesn't allocate (as much, at least), but you can't do things like await it twice, or use it with e.g. Task.WhenAll
Klarth
Klarth8/14/2022
Thaumanovic
Thaumanovic8/14/2022
I tend to use it when my method may never need to run asynchronously.
Thaumanovic
Thaumanovic8/14/2022
i.e. it never awaits
Message Not Public

Sign In and Join Server To See

8/14/2022
thinker227
thinker2278/14/2022
If I essentially have this
public async Task<string> GetStringAsync() {
  if (cachedValue is not null) return cachedValue;
  
  string value = await DoSomeOtherOperationAsync();
  cachedValue = value;
  return value;
}
Is it worth using ValueTask?
Message Not Public

Sign In and Join Server To See

8/14/2022
thinker227
thinker2278/14/2022
Nice
Message Not Public

Sign In and Join Server To See

8/14/2022
thinker227
thinker2278/14/2022
Why would you await it twice anyway?
Message Not Public

Sign In and Join Server To See

8/14/2022
canton7
canton78/14/2022
public Task<string> GetStringAsync() {
  if (cachedValue is not null) return cachedValue;
  
  string value = DoSomeOtherOperationAsync();
  cachedValue = value;
  return value;
}
Message Not Public

Sign In and Join Server To See

8/14/2022
thinker227
thinker2278/14/2022
Assuming you mean return Task.FromResult(cachedValue);
thinker227
thinker2278/14/2022
But that makes sense
Message Not Public

Sign In and Join Server To See

8/14/2022
thinker227
thinker2278/14/2022
An already completed task?
Message Not Public

Sign In and Join Server To See

8/14/2022
canton7
canton78/14/2022
Well, it'll complete when it completes. That's the point
Kuinox
Kuinox8/14/2022
My own rules are:
I know the async func will almost never complete synchronously => Task
If I know it will return synchronously most of the time => ValueTask
Kuinox
Kuinox8/14/2022
if it's internal function and I already didn't decided with 2 previous point => ValueTask
canton7
canton78/14/2022
No. cachedValue is a Task<string> (otherwise none of the other lines would compile)
canton7
canton78/14/2022
The point is that if someone calls GetStringAsync (which calls DoSomeOtherOperationAsync) you immediately cache the work-in-progress task. Then if someone else calls GetStringAsync before the task has completed, you give them back the same Task rather than calling DoSomeOtherOperationAsync a second time. If the task has completed, great, awaiting it is a free noop
canton7
canton78/14/2022
My view here is that single allocations are staggeringly cheap, and bugs are expensive. I'll always go with Task unless it's a high-perf scenario, in which case I'll have my profiler out and it can tell me if I need to move to ValueTask
Akseli
Akseli8/14/2022
🤨 cachedValue is a string not Task<string>
Akseli
Akseli8/14/2022
if you are directly awaiting the task

var value = await GetStringAsync();

use a valuetask

if you need to use the task

var task = GetStringAsync();
// await task later
then use a normal task
Message Not Public

Sign In and Join Server To See

8/14/2022
Kiel
Kiel8/14/2022
from my own personal asking around and seeing other people converse on the topic:
use ValueTask if you expect your method to return synchronously a greater-than-negligible amount of times. Use Task otherwise. ValueTask can, to my knowledge, offer a performance/speed gain over Task (if the method performs synchronous work only), but this is only noticible at massive scales where your method is called a LOT. it's not worth fretting over otherwise
Message Not Public

Sign In and Join Server To See

8/14/2022
Klarth
Klarth8/14/2022
A modern API? Not an older EAP/APM API?
Akseli
Akseli8/14/2022
difference between task and valuetask is that task allocates a new object on every call but valuetask only allocates a new object if the operation was asynchronous
Akseli
Akseli8/14/2022
otherwise the call is allocation free
canton7
canton78/15/2022
I'm saying turn it into a Task<string>
qqdev
qqdev8/15/2022
Do they return a Task maybe?
Message Not Public

Sign In and Join Server To See

8/15/2022
Klarth
Klarth8/15/2022
https://github.com/dotnet/aspnetcore/blob/c85baf8db0c72ae8e68643029d514b2e737c9fae/src/Components/Server/src/ProtectedBrowserStorage/ProtectedBrowserStorage.cs#L59 so these are mostly passthrough methods where async is ellided for perf. I assume MS knows how to do that properly...tagging the method names with Async can be confusing.
qqdev
qqdev8/15/2022
^ This is what I thought when reading your message
qqdev
qqdev8/15/2022
I think this is totally fine
thinker227
thinker2278/15/2022
how do you mark a thread as done :catsweat:
Kuinox
Kuinox8/15/2022
right click on it => archive
thinker227
thinker2278/15/2022
I figured that out and then yall posted again ._.
ContactFrequently Asked QuestionsJoin The DiscordBugs & Feature RequestsTerms & Privacy