236

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.

visual studio warning message

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; };
}
John Smith
  • 7,243
  • 6
  • 49
  • 61
VivekDev
  • 20,868
  • 27
  • 132
  • 202
  • 21
    You have [Nullable Reference Types](https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references) enables. If you weren't expecting this, and you're not sure how to use them, it's probably best to switch them off (until you've had a chance to get up to speed) – canton7 May 12 '21 at 14:12
  • 3
    This is giving warnings precisely to *increasy* your confidence in your code. Without it, it's easier to get null references errors down the road. – Alejandro May 12 '21 at 15:00
  • 10
    Regarding your update, for strings and other reference types `default!` is the same as `null!`. I prefer `null!` because using `default` doesn't add any useful information and can mislead people into thinking something other than `null` is being set there. – jmathew Feb 09 '22 at 18:14
  • 7
    [Nullable reference types docs](https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references): "Starting in .NET 6, they're enabled by default for new projects." – Holistic Developer Apr 15 '22 at 17:26
  • 32
    This is really silly. Objects and strings are expected to be nullable by default. – todji May 06 '22 at 16:04

14 Answers14

185

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.

Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197
  • 2
    I have completely closed Visual Studio, edited my csproj file to remove these lines, re-opened my solution, but I am still seeing the warnings. – Ray Goudie Jan 05 '22 at 03:08
  • 1
    @RayGoudie try clean and build again. Also do you have multiple projects in your solution? If yes then you have to remove the line from all the projects. – Vivek Nuna Jan 05 '22 at 03:13
  • There is only one project. Cleaning and rebuilding, as well as deleting the obj directory did not remove the warnings. – Ray Goudie Jan 05 '22 at 03:16
  • 4
    This feels more like a band-aid rather than an actual solution. I think @slate has the best solution and for the smaller projects I think Daryl Wagoner's option is great as well as Vivek's later suggestion of directly annotating a property as non-nullable. – GarudaLead Feb 05 '22 at 14:10
  • best option so far – DanielV Apr 01 '22 at 10:01
  • 2
    I think it's probably good to consider not disabling this though... whilst it's a bit of a pain for existing projects it does lend itself to the notion of null-safe code. – Rob Jul 18 '22 at 00:55
  • For those that say this is a bandaid... I'm getting this message on a FK relationship. `public virtual ...` So, I'm supposed to mark something as nullable that shouldn't be (and with no suitable default value), otherwise, be forced to look at the message indefinitely? – Sum None Jan 22 '23 at 07:44
  • @SumNone didn't get you – Vivek Nuna Jan 22 '23 at 07:46
  • This seems like a bunch of BS to me. Next thing you know, the `public int Id { get; set; }` property is going to have to be initialized to `0` –  Mar 31 '23 at 00:58
151

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.

Slate
  • 3,189
  • 1
  • 31
  • 32
  • 16
    A reasonable default for non-nullable strings is usually `string.Empty`. – Etienne de Martel May 12 '21 at 14:20
  • 5
    [Late-initialized properties, Data Transfer Objects, and nullability](https://learn.microsoft.com/en-us/dotnet/csharp/nullable-migration-strategies#late-initialized-properties-data-transfer-objects-and-nullability), goes over a 3 strategies to migrate when nullable reference types are switched on, Constructor binding, Create a nullable backing field and, Initialize the property to null with the null forgiveness operator. – Grant Sep 08 '21 at 22:58
  • 4
    The page Grant linked has changed and no longer has that section. Here it is on the Internet Archive: [Late-initialized properties, Data Transfer Objects, and nullability](http://web.archive.org/web/20210507001828/https://learn.microsoft.com/en-us/dotnet/csharp/nullable-migration-strategies) – Cameron Bielstein Oct 12 '21 at 23:23
  • 1
    But isn't string `string test;` by default test is null – variable Jan 14 '22 at 07:58
  • @variable Correct, which is not allowed if you have Nullable enabled. – Slate Jan 14 '22 at 09:25
  • When I write `null!` to get rid of the warning, for example - `public string Property{ get; set; } = null!;` - then when I instantiate the class, and set null into the Property `instance1.Property=null`, it doesn't give a warning - should it give a warning or not? – variable Jan 14 '22 at 09:28
  • 1
    @variable If your type is non-null `string`, then yes you will get warnings if you try to assign a null or potentially null value to your property, including if you previously initialized it with `null!`. If you are not getting warnings in that case, check nullable is on for that file, and that your type is not-null. – Slate Jan 18 '22 at 12:00
  • "string.Empty" is a great solution. I don't want to make a prop like Email nullable since I use ToLower() before saving on database. Using "string.Empty" I'm no getting null Exceptions anymore. Thanks for the solution. – Reza Taba Jul 01 '22 at 20:18
  • `string.Empty` is perfect. It's also useful when we are using a ViewModel binded with forms where we usually start with an empty form. – Kahan Bhalani Apr 11 '23 at 12:45
50

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

Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197
Simon Lehmann
  • 517
  • 4
  • 6
  • 1
    I'm not getting warning is I try to set the Property as null. – variable Jan 14 '22 at 08:00
  • 32
    If you specify `null!;` you are saying to the compiler "assign this null, but trust me, it's not null". See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-forgiving – Slate Jan 14 '22 at 09:25
  • This is so strange, I am working on .Net framework and I am doing a pet project to see the latest language features and this seems so wrong that they enable it by default in latest version... – David Petric Apr 02 '22 at 16:58
  • 2
    I think this answer is useful for using navigation properties with EF Core. Also I noticed in the EF core computer generated from the database scaffolding code the non nullable navigation properties have this by default. – Dave Barnett Sep 30 '22 at 12:29
36

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/dotnet/csharp/language-reference/keywords/required

Yoro
  • 805
  • 8
  • 17
19

For Entity Framework Working with nullable reference types:

public class NullableReferenceTypesContext : DbContext {
    public DbSet<Customer> Customers => Set<Customer>();
    public DbSet<Order> Orders => Set<Order>();
}
Zachary Scott
  • 20,968
  • 35
  • 123
  • 205
17

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;
    }
}
Meloy
  • 191
  • 1
  • 6
  • 3
    This is a very important aspect: maybe not in this particular thread's question, but there are cases where a property *must* be non-null by design. So a value must be provided when creating a class instance, thus, with the constructor. It is good that the default settings in dotnet enforce to deal with this for a reason. Only mark properties with "?" (nullable) when they actually *can* be null. Thus, all answers recommending "turn off the warnings" are completely careless. – Ingmar May 10 '22 at 11:08
  • @Ingmar I believe so as well. I am against declaring something as nullable if the program design vision is not for it. I've also ran into this for example if we wouldn't want to use a custom constructor `public List ListOfNumbers { get; set; } = new();`. Keep in mind, allocating data ( instantiating properties ) when it's not needed I believe is also code smell. – Zigzagas Dec 08 '22 at 13:12
14

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.

Darryl Wagoner WA1GON
  • 967
  • 1
  • 10
  • 31
  • 2
    Is there no way to annotate the property itself as being non-null? Otherwise, libraries like Hot Chocolate (GraphQL) which use reflection have no way of knowing. – Rei Miyasaka Aug 19 '21 at 05:27
  • My question was near identical to the OP's; only difference was specific to the `[Inject]` attribute usage for Blazor WASM. – jjhayter Apr 19 '22 at 15:47
10

Click on Project Name -> Open .csproj file

Replace <Nullable>enable</Nullable>

With <Nullable>disable</Nullable>
rohit.khurmi095
  • 2,203
  • 1
  • 14
  • 12
7

In Visual Studio 2022 v17.2.3 Visual Studio Project Settings

Right click your Project title > Properties > Application > Packaging > Under the "Build" section > Set "Nullable" = "Enable" in the dropdown.

Beau
  • 71
  • 2
  • 5
4

Just put:

#nullable disable

at the top of a Razor Page

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Alfi
  • 111
  • 1
  • 6
2

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 this Fody Weaver to have it done for you.

jjhayter
  • 352
  • 4
  • 19
1

When working with a list of String you can use:

public List<string> ? nameOfPublicConstructor { get; set; }
Adriaan
  • 17,741
  • 7
  • 42
  • 75
0

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. In other words, if your database has data that is non-nullable, your code's data structure for importing that data should also be non-nullable, vice versa.

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 31 '22 at 21:39
0
class programdemo
{
    //fild propertes
    private string Name =string.Empty;
    private int adg;
    private string? typework;

   // encapsuolation propertes
   // this Auto Properties
   public string nmae { get; set; } =string.Empty;

   // Full Properties
   public int Adg  { get { return adg;} set { adg =value;} }
    public string? Typework {get {return typework;} set {typework =value;} } 

    // Methodes
    public void resolut()
    {

    }
}