Reputation: 1678
Is it possible to resolve this warning:
Converting null literal or possible null value to non-nullable type.
without suppression for this C# code
List<PropertyInfo> sourceProperties = sourceObject.GetType().GetProperties().ToList<PropertyInfo>();
List<PropertyInfo> destinationProperties = destinationObject.GetType().GetProperties().ToList<PropertyInfo>();
foreach (PropertyInfo sourceProperty in sourceProperties)
{
if (!Equals(destinationProperties, null))
{
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
PropertyInfo destinationProperty = destinationProperties.Find(item => item.Name == sourceProperty.Name);
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
}
}
that uses Reflection.
I am using Visual Studio 2019 and .NET Core 3.1.
Upvotes: 41
Views: 97485
Reputation: 15759
All reference types in C# remain implicitly nullable. What was added is Microsoft's new null checking system which tries to alert you to cases where nulls appear that could cause runtime exceptions. The reason is Microsoft has come up with the concept of "non-null" versus "maybe-null" logic for everything now.
This means that regardless of the nullable properties of reference types, unless explicitly set to nullable (MyType? obj) they still could be maybe-nulls and trigger compilation warnings like this. However, even when you make your Types nullable ?
, they still risk blowing up the non-null and maybe-null types and logic in your code. Do not trust nullable operators ?
to solve your problems, as even nullable reference types using the ?
operator could still blow up code when working with non-null types.
So nullable types do not solve your problems, just stop the alerts as you are telling the compiler to expect nulls now.
What is worse, we do not have a non-null operator for reference types in .NET (It's been 25 years and we still cannot create non-null types?) That would enforce avoidance of nulls. We have the ??= null coalesce equality operation, but it does not enforce non-null object creation.
The same problem exists using the null-forgiving operator !
. All it does is suppress nullable warnings but does NOT fix the null exception risks! So I try and avoid its use. Do not trust your code logic, trust your objects. They should not be null
or nullable unless you are working with nulls and checking for them explicitly.
My solution in dealing with the "maybe null" scenarios is by either checking for nulls (which may or may not stop the null check alerts) or plan on assigning a default object when something is maybe-null, like shown below. All reference types are maybe-null out of the box anyway so why leave the possibility open they could blow up other parts of your code?
My Default Object Solution has several advantages:
Below, I am using the null coalescing operator ??
as a quick way to assign these objects:
PropertyInfo destinationProperty =
destinationProperties.Find(item => item.Name == sourceProperty.Name)
?? new PropertyInfo();
I assigned a default empty object of my Type which has the advantage that it will NEVER BLOW UP access by other types, and it gives you total control over what your default objects with default values should do, should display, or how they are cast. No more nulls!
In your PropertyInfo class you could also assign default non-null values to all your class properties so they also have values and can be cast, extracted, etc. This solution also adds cast safety, or if you decide to make your Type nullable later and mix those nullables with maybe null logic. You can still explicitly use nulls if you like or switch to the default object. It simply allows you to use default references in your application that really need default objects when working with a wide variety of other code and other objects that consume them. You can now build logic around "Default Values" rather than "Unknown Values" (no value), which is what null often means in the coding world.
You should not be counting on null
assigned to nullables for any kind of logic, anyway.
Upvotes: 2
Reputation: 11
You can do one thing, instead of using the type 'PropertyInfo'
PropertyInfo destinationProperty = destinationProperties.Find(item => item.Name == sourceProperty.Name);
You can use 'var'
var destinationProperty = destinationProperties.Find(item => item.Name == sourceProperty.Name);
Upvotes: 0
Reputation: 1293
You can take one of the solutions proposed by @codecaster or, as Microsoft docs describe, you can alternatively disable this warning by adding the null forgiving operator, !
to the right-hand side
PropertyInfo destinationProperty = destinationProperties.Find(item => item.Name == sourceProperty.Name)!; //<------ note the "!" operator at the end of the line
Upvotes: 5
Reputation: 151588
Find()
can return null
when what you're looking for is not found. So destinationProperty
can become null.
So the solution would be to declare it as nullable:
PropertyInfo? destinationProperty = ...
Or to throw an exception:
PropertyInfo destinationProperty = ...Find() ?? throw new ArgumentException(...)
Upvotes: 67