-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Remove "Result" property of ValueTask<T> #8902
Conversation
Hi @ljw1004, I'm your friendly neighborhood .NET Foundation Pull Request Bot (You can call me DNFBOT). Thanks for your contribution! TTYL, DNFBOT; |
@ljw1004, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR. |
In corefx /cc @stephentoub |
cc: @terrajobst, @KrzysztofCwalina, @weshaggard
Yes. Lucian, you would need to fix all existing uses of this as well. In this PR, please fix all uses in corefx, so that we don't then break when these changes get built into packages and we try to consume those packages. I assume ASP.NET would want you to submit fixes there at the same time so that they don't break when they consume the latest. Please also fix corefxlab, where the Channels project uses ValueTask.
The same is true of .GetAwaiter().GetResult(). You can argue that's better because it's not a property and it's more typing, but it's still blocking. Further, blocking can be necessary more often than we'd like.
So there can't ever be a new API named "Result" that has different exception-related behaviors from a "Result" we shipped in .NET 4? 😄
You've not mentioned the other impact here: it's now a bit harder to get the value out of a ValueTask created from a value even if you know there won't be blocking, e.g. if IsCompleted is true, if you created the task from the ctor "new ValueTask(42)", etc. To extract that value, you previously could just say ".Result", which is simple and cheap. If you're in an async method, you can use "await valueTask", but you're not always in an async method when using this type. So now to extract the value, you need to say ".GetAwaiter().GetResult()". From my perspective, this change does have cost and doesn't improve much: if someone wants to get the value, they're now just going to type more, typing ".GetAwaiter().GetResult()" instead of ".Result", or worse writing an async method that awaits the thing and then calling ".Result" on the returned But for all my "devil's advocate" pushback in this comment, I actually don't feel strongly about it. If others like the idea of removing it, I'm fine with it. |
Maybe replace with something like? bool TryGetResult<T>(out T value)
{
if (_task == null)
{
value = _result;
return true;
}
else if (_task.Status == TaskStatus.RanToCompletion)
{
value = _task.GetAwaiter().GetResult();
return true;
}
value = default(T);
return false;
} As it internalizes dependency on the pattern to avoid blocking; but still allows the fast path for completed things. |
We should separate out removing the existing member from adding a replacement. One needs to be done immediately if it's going to be done, the other can be done if desired later. That said, I'm not sure this adds much. We're talking about the difference between: if (vt.IsCompletedSuccessfully)
{
Use(vt.Result);
}
else
{
...
} vs
but I don't have any fundamental objections to adding a TryGetResult method at some point if folks found it helpful. It does map to the Try* pattern, so maybe that would be useful for folks that go in search of something like it. |
First relies on the user correctly writing non-blocking checks, which is one of the suggested concerns here with Try* with It could be argued it would be a good method to add to Will raise an suggestion/issue... |
I trust the users to do the right thing; no need to baby-proof something that's already been in .NET for years. This doesn't add any value IMHO. |
Personally, I don't see this adding much value. As @stephentoub said, we're blocking regardless. However, Also, considering we're quite late in Escrow and there are many upstream dependencies outside of CoreFx I'm inclined to say no 👎 |
Okay, closing this pull request. |
I think we should remove the "Result" property