-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
False positive: CS8600 - Converting null literal or possible null value to non-nullable type #73306
Comments
Why |
Since this is the way generic arguments are annotated, see here and search for "annotate generic out arguments". You can only use |
To me, this looks correct. The type parameter to bool IValueHolder<string?>.TryGetValue<string?>(out string? value) At this point, the note from a little later in the same bullet point of the linked nullability guidelines comes into play:
As evidence of this, the warning goes away (8.0.203!) if the call is made in one of these ways: // here, `var` is inferred as `string?` due to the annotation
// but holder is still typed as `IValueHolder<string>`
if (holder.TryGetValue(out var value))
{
string copy = value; // no warning
}
if (holder.TryGetValue<string>(out string? value))
{
string copy = value; // no warning
} …though IDE0001 kicks in for me for the type argument for the latter. Another option would be to implement public bool TryGetValue([MaybeNullWhen(false)] out T value)
{
value = HasValue ? Value : default;
return HasValue;
} This also produces no warning, but I don't know what business value |
@chrisoverzero Yeah, thanks to your explanation regarding type inference, I think I found an explanation for the covariance thing and the different behaviors (covariance vs. no variance). With covariance, the following assignment is valid: IValueHolder<string?> left;
IValueHolder<string> right = new ValueHolder<string>("foo");
left = right; With no variance, this assignment results into a compile time warning. Therefore I think this is the reason why with covariance the following code IValueHolder<string> holder = new ValueHolder<string>("foo");
holder.TryGetValue(out string? value); // (1) is inferred as IValueHolder<string> holder = new ValueHolder<string>("foo");
holder.TryGetValue<string?>(out string? value); ..., because an In contrast, when we do not use covariance the following code IValueHolder<string> holder = new ValueHolder<string>("foo");
holder.TryGetValue(out string? value); // (1) is inferred as IValueHolder<string> holder = new ValueHolder<string>("foo");
holder.TryGetValue<string>(out string? value); ..., because an If some one of the language designers can confirm my interpretation of the behavior, it's obviously not a bug, and in turn we could close this issue. HINTOf course I could use an instance method instead of an extension method, or I could use |
There is one more observation I made. The following code (as proposed by @chrisoverzero) seems to work correctly: public static class ValueHolderExtensions
{
public static bool TryGetValue<T>(this IValueHolder<T> holder, [NotNullWhen(true)] out T? value)
{
value = holder.HasValue ? holder.Value : default;
return holder.HasValue;
}
} But this is against the guidelines describes here, so I wonder if the specification has changed in the meantime. IIRC writing |
You can use NotNullWhen with generics just fine :-) Are you sure that doesn't fix things here? |
Yeah, Can somebody from the language designers confirm that |
Interesting: Both attributes appear to be allowed with generics. |
I am one of hte lang designers :D |
Note that if you do have a |
@sharwell I see, and now I understand why they used both attributes in |
I feel there is some bug here because:
Curious what you think @jcouv. |
Version Used: VS 17.8.7 (Compiler Version 4.8.0-7.23572.1, Language Version 12.0)
Steps to Reproduce:
Try to compile the code below (see also sharplab).
Diagnostic Id:
CS8600
Expected Behavior:
Should compile without warning.
Actual Behavior:
Issues a warning.
Observation:
If you remove the covariance from the interface definition like
..., the code compiles without warning.
The text was updated successfully, but these errors were encountered: