[BUG] Response<T>.HasValue is inconsistent and returns unexpected results
See original GitHub issueLibrary name and version
Azure.Storage.Queues 12.13.1
Describe the bug
QueueClient.ReceiveMessageAsync
returns a Response<QueueMessage>
result, which is actually of type ValueResponse<T>
. This internal class does NOT override the Response<T>.HasValue
property.
As a result, when checking the HasValue
property, it unexpectedly returns true, even if Value
is false. This is misleading and led to broken app code based on this assumption.
Expected behavior
HasValue
should reflect the current state of the Value
property.
Actual behavior
It always returns true, regardless of whether or not Value
has a value that is different from default(T)
.
Reproduction Steps
var response = await _queueClient.ReceiveMessageAsync();
if (!response.HasValue)
{
// this block should not be entered if response.Value is default(T) but it is
}
Environment
No response
Issue Analytics
- State:
- Created 5 months ago
- Reactions:1
- Comments:16 (8 by maintainers)
Top Results From Across the Web
c# - Rewrite HasValue to the ?? Operators
Value as it omits the has-value check. ... It returns the left-hand operand if it is not null; otherwise it returns the right...
Read more >Is it better to return null or a new object? : r/csharp
Not getting a result, however, doesn't qualify as exceptional so you return null or an empty object. There's no right answer. The topic...
Read more >C#.NET Guidelines: Implementation | Azure SDKs
Type of value comparison should be selected on per-service basis, if the service is inconsistent with how string values are returned the case-insensitive ......
Read more >How do you check if int is “null” in C# (c#, .net, tipagem ...
You can check whether a nullable integer has a value or not using the HasValue property, like this: if(myNullableInt.HasValue) {. // myNullableInt has...
Read more >The Shape of Things to Come: Why Is Climate Change So ...
This shape is consistent with results from multiensemble GCM studies as well as a variety of observationally based estimates. The lighter curves, to...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I think that’s the right choice. Any code that throws where it didn’t throw previously is a much poorer experience than a property that doesn’t actually reflect the current state.
My guess is that most devs are currently checking
Value is null
and, if it changes to throw, their code suddenly breaks without warning.By implementing your suggestion of suppressing nullability checks and preserving
Value
functionality, while addingHasValue
functionality, it is a net improvement, even if nullability checks suffer. And since anything else is too large of a breaking change, I’m not sure what else you could do other than modifying my original suggestion of aninternal NullableValueResponse<T>
type that handles the nullability check suppression and is returned as the public type. That said, I’m guessing that also is too large of a breaking change.I appreciate the effort to come up with a creative solution!
This would be a massive breaking change. We don’t do these, even in major versions.
To address your particular concern about breaking code if we start throwing, we could still do bullets 2 and 3 in most cases, but in cases where we today return null, we could keep returning it and just suppress the compiler nullability checks, i.e. return null despite Response.Value being non-nullable. It’s not super clean, but I am not sure we have better options.