3355307
3355307

Reputation: 1678

Converting null literal or possible null value to non-nullable type

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.

enter image description here

I am using Visual Studio 2019 and .NET Core 3.1.

Upvotes: 41

Views: 97485

Answers (4)

Stokely
Stokely

Reputation: 15759

Use a Default Object with Null Coalescing (??) Operator

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:

  1. Guarantees an object (non-null value)
  2. Allows safe casting between nullable, maybe-null, and non-null types
  3. Avoids need for null checks elsewhere
  4. Avoids assigning nullable and null-forgiving operators just to suppress one narrow type of alert or warning
  5. Removes all future null alerts in code accessing the reference later (methods, for example)
  6. Allows developers to explicitly code for fallback situations at first use rather than unknowns, no value, missing value, or bad values later
  7. Avoids abusing the unhandled exceptions system or NullReferenceException calls in .NET to handle unknown and unexpected null-related errors. They are always avoided and handled!

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

Pankaj Singh
Pankaj Singh

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

LeonardoX
LeonardoX

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

CodeCaster
CodeCaster

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

Related Questions