-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Nullable warning for cast through object? #34976
Comments
Note that the above case is a simplified version of a more common pattern. Because C# doesn't let you cast from a generic T to a specific value type, code optimizing for specific types often casts through object, e.g. private static bool Method<T>(T value)
{
if (typeof(T) == typeof(bool))
return (bool)(object?)value;
return false;
} This similarly warns, even though there's no way that |
The warning in the simplified example is actually by design:
The result of an explicit cast to a nullable reference type is treated as nullable. Although clearly, when casting from a value type, the value is not null. Unfortunately, the explicit cast behavior makes it difficult to handle the generic example which requires a cast to
Of course,
An alternative is to change the type test:
|
But it can never be null... why does the flow analysis consider it possibly null? I'm struggling to understand "The warning in the simplified example is actually by design" contrasted with "Although clearly, when casting from a value type, the value is not null.". |
The ability to override the compiler's analysis by explicitly casting to a nullable reference type permits the programmer to provide information (that a value might be null) where the compiler's analysis may not be precise. The idea is that if you don't think the value can be null, don't cast to a nullable reference type. |
By that logic, shouldn't this warn on dereferencing o1? It doesn't: using System;
#nullable enable
public class C {
public void M(string s1)
{
if (s1 != null)
{
s1.GetHashCode();
object? o1 = s1;
o1.GetHashCode();
}
}
} To be clear, I don't think either case should warn. But in both I'm casting a known-non-null to |
There is no cast in this. |
Oh you literally meant an explicit cast. Ok, it's then really wierd to me that this warns for both: #nullable enable
public class C {
public void M(bool b, string s)
{
object? o1 = (object?)b;
object? o2 = (object?)s;
o1.GetHashCode();
o2.GetHashCode();
}
} but this doesn't for either: #nullable enable
public class C {
public void M(bool b, string s)
{
object? o1 = b;
object? o2 = s;
o1.GetHashCode();
o2.GetHashCode();
}
} I don't see why an explicit vs implicit casts should impact the warnings issued. |
We could have added a new syntax or operator for the programmer to say "this expression might be null", but the explicit cast seems to fit the bill. If you believe the expression may be null, cast to Implicit conversions, on the other hand, have no syntax. For an implicit conversion, the compiler tracks the type as a nullable type but with a known non-null value at that point in the program. |
I would if I could, but in the second example the compiler warns if I try to use
Can you share an example where you'd want a warning in an example like the first, where it's impossible for the value to be null and the compiler can see that? I'm really curious. We're spending a lot of time |
The compiler doesn't distinguish values that are "believed" to be non-null from those that are "impossible" to be non-null. They tracked states are (1) null is not expected, and (2) null is expected. There is no tracked state of "null is actually impossible". If you'd prefer that the compiler refine the set of tracked states, that would be a language change suitable for consideration in |
I don't believe "examples like the first" are intended use cases for casting to a nullable type. I don't know why that example casts to a nullable type. It seems like a bad idea. |
Should the language recognize |
Hmm, that only works for cases where the |
The compiler doesn't use the fact that |
This would something that could reasonably done by a theorem-prover-styly analysis (dotnet/csharplang#2388) |
Closing and tracking as part of dotnet/csharplang#2388 |
Version used:
Today's master
Repro:
cc: @dotnet/nullablefc
The text was updated successfully, but these errors were encountered: