简体   繁体   中英

Non-nullable property must contain a non-null value when exiting constructor. Consider declaring the property as nullable

I have a simple class like this.

public class Greeting
{
    public string From { get; set; }
    public string To { get; set; } 
    public string Message { get; set; }
}

Strangely I get the following warning.

Severity    Code    Description Project File    Line    Suppression State
Warning CS8618  Non-nullable property 'From' must contain a non-null value when exiting constructor. 
Consider declaring the property as nullable.    MxWork.Elsa2Wf.Tuts.BasicActivities  
D:\work\MxWork\Elsa2.0WfLearning\MxWork.Elsa2.0Wf.Tuts\src 
\MxWork.Elsa2Wf.Tuts.BasicActivities\Messages\Greeting.cs   5   Active

I am baffled. These new kind of messages that it throws pulls down my confidence. I got them from all the three properties. And this has suddenly appeared.

Can some one please suggest how this can be mitigated.

视觉工作室警告消息

Update

These days I have seen using default! like so, and its working.

public class Greeting
{
    public string From { get; set; } = default!;
    public string To { get; set; } = default!;
    public string Message { get; set; } = default!;
}

Also you may put a question mark symbol(?) to indicate that the type is nullable, if you feel appropriate as follows.

public class Greeting
{
    public string? From { get; set; };
    public string? To { get; set; };
    public string? Message { get; set; };
}

If you don't want this, you can disable this by deleting the below line from the csproj file or setting it as disable . By default value is disable .

<Nullable>enable</Nullable>

Here is the official documentation.

The compiler is warning you that the default assignment of your string property (which is null) doesn't match its stated type (which is non-null string ).

This is emitted when nullable reference types are switched on, which changes all reference types to be non-null, unless stated otherwise with a ? .

For example, your code could be changed to

public class Greeting
{
    public string? From { get; set; }
    public string? To { get; set; } 
    public string? Message { get; set; }
}

to declare the properties as nullable strings, or you could give the properties defaults in-line or in the constructor:

public class Greeting
{
    public string From { get; set; } = string.Empty;
    public string To { get; set; } = string.Empty;
    public string Message { get; set; } = string.Empty;
}

if you wish to retain the properties' types as non-null.

You can annotate a property directly as non-nullable.

public string Property{ get; set; } = null!;

And it will give a warning if user tries to set the Property as null

Having nullable reference types turned on will save you a lot of heartaches when it comes to running your application. The problem with a lot of warnings is that most may not cause a problem, but it may hide that one that is causing a hard-to-find bug.

There are a few gotchas in using it like the question points out and answer very well by Slate and others.

It is a very good idea to have as near as possible to zero warning.

With nullable enabled, it produces a lot of warnings. Many times the compiler just knows something could be null. However, you being smarter than the compiler you know that by the time it reaches that code it won't be null.

For example:

    public partial class Exams: ComponentBase
    {
    [Inject] private IQuestionPoolFetchService? QPoolService { get; init; }


        private async Task FetchQuestionPool()
        {
            await QPoolService.GetAllQuestionsFromText();
        }

This will throw a CS8602 warning. Because maybe somehow the DI will send a null. Of course, we know that isn't going to happen.

You could get rid of the warning with #prama like:

    public partial class Exams: ComponentBase
    {
    [Inject] private IQuestionPoolFetchService? QPoolService { get; init; }


        private async Task FetchQuestionPool()
        {
#pragma warning disables CS8602 // Dereference of a possibly null reference.
            await QPoolService.GetAllQuestionsFromText();
#pragma warning restore CS8602 // Dereference of a possibly null reference.
        }

This is very ugly code and gets worst if you have to repeat it many times.

A better solution: Using the null-forgiving operator. "!"

public partial class Exams: ComponentBase
{
[Inject] private IQuestionPoolFetchService? QPoolService { get; init; }


    private async Task FetchQuestionPool()
    {
        await QPoolService!.GetAllQuestionsFromText();
        // null-forgiving ^
    }

This tells the compiler hey, I know this could be null, but it won't be.

You can also implement a constructor to remove the error.

public class Greeting
{
    public string From { get; set; }
    public string To { get; set; }
    public string Message { get; set; }

    public Greeting(string from, string to, string message)
    {
        From = from;
        To = to;
        Message = message;
    }
}

For Entity Framework Working with nullable reference types:

public class NullableReferenceTypesContext : DbContext {
    public DbSet<Customer> Customers => Set<Customer>();
    public DbSet<Order> Orders => Set<Order>();
}

In Visual Studio 2022 v17.2.3 Visual Studio Project Settings

When I searched for this question, specifically for Blazor WebAssembly [WASM], I found an alternative to Darryl Wagoner WA1GON's answer.

Using [DisallowNull] which is a precondition guard according to Microsoft's docs on Attributes for null-state static analysis interpreted by the C# compiler . It is well worth reading about more in-depth.

public partial class UploadView : FluxorComponent
{
    private static readonly Serilog.ILogger logger = Serilog.Log.ForContext<UploadView>();

    [Parameter][DisallowNull] public string? UploadHeader { get; set; }
    [Parameter][DisallowNull] public EventCallback<SaveFile>? OnUploaded { get; set; }

    [Inject][DisallowNull] private IState<UploadViewState>? State { get; set; }
    [Inject][DisallowNull] private IDispatcher? Dispatcher { get; set; }

// NOTE: I included this as an example of trying to use the null-forgiveness / old school approach 
    public UploadViewState Model {
        get {
            if (State is null) { logger.Warning("{@Component}.Model - State is null", GetType().Name); }
            if (State?.Value is null) { logger.Warning("{@Component}.Model - State.Value is null", GetType().Name); }

            return State!.Value!;
        }
    }

    protected override void OnInitialized()
    {       
        base.OnInitialized();

        Dispatcher.Dispatch(new Initialized());
        Dispatcher.Dispatch(new UploadFileSizeChanged(524288000));

        logger.Debug("{@Component} - Initialized", GetType().Name);
    }

// yada yada...
}

NOTE: If this seems like a lot of work for you to maintain you can use thisFody Weaver to have it done for you.

When working with a list of String you can use:

public List<string> ? nameOfPublicConstructor { get; set; }

Since C#11 ( .NET 7.0 ) you can add a required modifier.

public class Greeting
{
    public required string From { get; set; }
    public required string To { get; set; } 
    public required string Message { get; set; }
}

This feature aims to improve how we initialize objects that do not rely on constructor parameters so it won't feel like a cheat.

But with the required modifier, you won't be able to use var greeting = new Greeting(); to create an object instance. Now to create an object instance you must do something like:

var greeting = new Greeting()
{
   "Me",
   "You",
   "Some msg..",
};

Originally answer was posted on: What is best way to create .NET6 class with many non-nullable properties?

More detailed info: https://learn.microsoft.com/en-us/do.net/csharp/language-reference/keywords/required

Just put:

#nullable disable

at the top of a Razor Page

Click on Project Name -> Open.csproj file

Replace <Nullable>enable</Nullable>

With <Nullable>disable</Nullable>

If you are using an entity framework, your nullable/non-nullable attribute should align with your database, which will be either NULL or NOT NULL; whether it be SQL, json, etc.. This is just my opinion, but I prefer consistency over some warning at the build level.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM