退出构造函数时,不可为空的属性必须包含非空值。考虑将属性声明为可为空

     2023-04-12     260

关键词:

【中文标题】退出构造函数时,不可为空的属性必须包含非空值。考虑将属性声明为可为空【英文标题】:Non-nullable property must contain a non-null value when exiting constructor. Consider declaring the property as nullable 【发布时间】:2021-08-02 22:01:18 【问题描述】:

我有一个像这样的简单课程。

public class Greeting

    public string From  get; set; 
    public string To  get; set;  
    public string Message  get; set; 

奇怪的是,我收到以下警告。

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

我很困惑。它抛出的这些新类型的信息降低了我的信心。 我从所有三个属性中得到它们。 而这突然出现了。

有人可以建议如何减轻这种情况。

更新

这些天我看到像这样使用 default! 并且它的工作原理。

public class Greeting

    public string From  get; set;  = default!;
    public string To  get; set;  = default!;
    public string Message  get; set;  = default!;

如果你觉得合适的话,你也可以放一个问号(?)来表示该类型是可以为空的。

public class Greeting

    public string? From  get; set; ;
    public string? To  get; set; ;
    public string? Message  get; set; ;

【问题讨论】:

您已启用Nullable Reference Types。如果您没有预料到这一点,并且您不确定如何使用它们,最好将它们关闭(直到您有机会跟上进度) 这正是为了增加您对代码的信心而发出警告。没有它,以后更容易出现空引用错误。 关于您的更新,对于字符串和其他引用类型,default!null! 相同。我更喜欢null!,因为使用default 不会添加任何有用的信息,并且会误导人们认为null 之外的其他内容被设置在那里。 【参考方案1】:

如果您不想这样做,可以通过从 csproj 文件中删除以下行或将其设置为 disable 来禁用此功能。默认值为disable

<Nullable>enable</Nullable>

Here是官方文档。

【讨论】:

解决问题太好了 我已完全关闭 Visual Studio,编辑我的 csproj 文件以删除这些行,重新打开我的解决方案,但我仍然看到警告。 @RayGoudie 尝试清理并再次构建。您的解决方案中是否还有多个项目?如果是,那么您必须从所有项目中删除该行。 只有一个项目。清理和重建,以及删除 obj 目录并没有删除警告。 这感觉更像是一种创可贴,而不是真正的解决方案。我认为@slate 有最好的解决方案,对于较小的项目,我认为 Daryl Wagoner 的选择以及 Vivek 后来直接将属性注释为不可为空的建议都很棒。【参考方案2】:

编译器警告您,字符串属性的默认分配(为 null)与其声明的类型(非 null string)不匹配。

当nullable reference types 被打开时发出,这会将所有引用类型更改为非空,除非用? 另有说明。

例如,您的代码可以更改为

public class Greeting

    public string? From  get; set; 
    public string? To  get; set;  
    public string? Message  get; set; 

将属性声明为可为空的字符串,或者您可以在线或在构造函数中提供属性默认值:

public class Greeting

    public string From  get; set;  = string.Empty;
    public string To  get; set;  = string.Empty;
    public string Message  get; set;  = string.Empty;

如果您希望将属性的类型保留为非空。

【讨论】:

不可为空字符串的合理默认值通常是string.Empty Late-initialized properties, Data Transfer Objects, and nullability,介绍了在可空引用类型打开时迁移的 3 种策略、构造函数绑定、创建可空支持字段以及使用空宽恕运算符将属性初始化为空。跨度> Grant 链接的页面已更改,不再包含该部分。它在 Internet 档案中:Late-initialized properties, Data Transfer Objects, and nullability 但不是字符串string test; 默认测试为空 @variable 正确,如果您启用了 Nullable,则不允许这样做。【参考方案3】:

您可以将属性直接注释为不可为空。

public string Property get; set;  = null!;

如果用户尝试将Property 设置为null,它会发出警告

【讨论】:

我没有收到警告是我尝试将属性设置为空。 如果您指定null!;,您是在对编译器说“分配这个空值,但相信我,它不是空值”。见docs.microsoft.com/en-us/dotnet/csharp/language-reference/…【参考方案4】:

在运行应用程序时,启用可为空的引用类型将为您省去很多麻烦。许多警告的问题在于,大多数警告可能不会导致问题,但它可能会隐藏导致难以发现的错误的警告。

使用它有一些陷阱,就像问题指出的那样,Slate 和其他人回答得很好。

让警告尽可能接近于零是一个非常好的主意。

启用 nullable 后,它会产生很多警告。很多时候,编译器只知道某些东西可能为空。但是,您比编译器更聪明,您知道当它到达该代码时它不会为空。

例如:

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


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

这将引发 CS8602 警告。因为也许 DI 会以某种方式发送一个空值。当然,我们知道这不会发生。

您可以使用 #prama 来消除警告,例如:

    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.
        

这是非常难看的代码,如果你必须重复多次,就会变得更糟。

更好的解决方案: 使用容错运算符。 “!”

public partial class Exams: ComponentBase

[Inject] private IQuestionPoolFetchService? QPoolService  get; init; 


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

这告诉编译器嘿,我知道这可能为空,但它不会。

【讨论】:

有没有办法将属性本身注释为非空?否则,像 Hot Chocolate (GraphQL) 这样使用反射的库是无法知道的。【参考方案5】:

您还可以实现构造函数来消除错误。

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;
    

【讨论】:

【参考方案6】:

对于实体框架Working with nullable reference types:

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

【讨论】:

构造函数是在 C# 中初始化类中不可为空的属性的唯一方法吗?

】构造函数是在C#中初始化类中不可为空的属性的唯一方法吗?【英文标题】:Isconstructortheonlywaytoinitializenon-nullablepropertiesinaclassinC#?【发布时间】:2020-04-1904:58:39【问题描述】:我已切换到在使用C#8的项目中启用可为空。现在我... 查看详情

必须初始化不可为空的实例字段“taskTitle”

...错误(必须初始化不可为空的实例字段taskTitle),尽管在构造函数中初始化实例字段.所以,我假设每当创建这个类实例时,用户都需要提供两个成 查看详情

可为空的引用类型和构造函数警告

】可为空的引用类型和构造函数警告【英文标题】:Nullablereferencetypesandconstructorwarnings【发布时间】:2020-07-2801:51:15【问题描述】:我正在尝试在我的项目中采用C#8的可为空引用类型,并使其与EFCore顺利配合。在thisguide之后,我... 查看详情

无法删除用户外部登录

...息:操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或 查看详情

如何在构造函数主体中初始化不可为空的成员?

】如何在构造函数主体中初始化不可为空的成员?【英文标题】:HowdoIinitializenon-nullablemembersinaconstructorbody?【发布时间】:2021-06-1721:23:54【问题描述】:我已经以这种方式在Dart中创建了我的类,但我得到了Non-nullableinstancefield\'te... 查看详情

外键约束,带有子对象集合的 EF

...误“操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关外键属性设置为空值。如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者不相关的对象必须删除 查看详情

必须初始化不可为空的实例字段

】必须初始化不可为空的实例字段【英文标题】:Non-nullableinstancefieldmustbeinitialized【发布时间】:2021-07-0602:57:10【问题描述】:classFoointcount;//Errorvoidbar()=>count=0;为什么我已经在bar方法中初始化它时看到错误?如果count被标记为... 查看详情

NetCore 6 - 将空文字或可能的空值转换为不可为空的类型

】NetCore6-将空文字或可能的空值转换为不可为空的类型【英文标题】:NetCore6-Convertingnullliteralorpossiblenullvaluetonon-nullabletype【发布时间】:2021-11-1119:32:05【问题描述】:我将项目更新到NetCore6,但收到警告:Convertingnullliteralorpossibl... 查看详情

oracle只显示不为空的列

...户名密码登录指定数据库。2/8在创建数据表时将字段设置为空,新建一个SQL窗口,输入一下语句:createtableSTUDENT(stuidvarchar2(11)notnull,stunamevarchar2(50),sexchar(1),agenumber(2))并执行。该语句会创建一个名为STUDENT的数据表并在stuid字段后面加... 查看详情

Kotlin 中的非空值产生空指针异常

...ion【发布时间】:2019-03-3114:32:29【问题描述】:我有一个不可为空的值数组,如下所示:privatevaldogs=ArrayListDog()//replacewith<>它是这样填充的:valdog=Dog()dog.name=“bob”dogs.add(do 查看详情

控制器属性不能包含非标量\/非空值

】控制器属性不能包含非标量\\\\/非空值【英文标题】:Controllerattributescannotcontainnon-scalar\\/non-nullvalues控制器属性不能包含非标量\\/非空值【发布时间】:2017-02-1323:21:06【问题描述】:我想为我的控制器对象提供这样的hinclude.js... 查看详情

C# 8 中的不可为空的引用类型在运行时可以为空吗?

】C#8中的不可为空的引用类型在运行时可以为空吗?【英文标题】:Cananon-nullablereferencetypeinC#8benullinruntime?【发布时间】:2020-04-1905:05:53【问题描述】:在我看来,确实不能保证不可为空的变量永远不会为空。想象一下,我有一... 查看详情

Flutter-不可为空的实例字段'questionAnswer','questionText'必须初始化

】Flutter-不可为空的实例字段\\\'questionAnswer\\\',\\\'questionText\\\'必须初始化【英文标题】:Flutter-Non-nullableinstancefield\'questionAnswer\',\'questionText\'mustbeinitializedFlutter-不可为空的实例字段\'questionAnswer\',\'questionText\'必须初始化【发布... 查看详情

不可为空的实例字段 ['controller'] 必须在颤振中初始化

】不可为空的实例字段[\\\'controller\\\']必须在颤振中初始化【英文标题】:Non-nullableinstancefield[\'controller\']mustbeinitializedinflutter不可为空的实例字段[\'controller\']必须在颤振中初始化【发布时间】:2021-11-0810:58:01【问题描述】:美... 查看详情

颤振错误->必须初始化不可为空的“项目”

】颤振错误->必须初始化不可为空的“项目”【英文标题】:FlutterError->Non-nullable\'items\'mustbeinitialized【发布时间】:2021-10-2909:06:18【问题描述】:classCatalogModelstaticList<Item>items;staticItemgetById(intid)=>items.firstWhere((element)=& 查看详情

使 LEAST() 函数返回一个非空值

】使LEAST()函数返回一个非空值【英文标题】:MakeLEAST()functionreturnanon-emptyvalue【发布时间】:2018-07-1217:41:20【问题描述】:我有5列日期(col1、col2、col3、col4、col5),其中一些是空的或带有null。我需要从所有这些列中找到一个最... 查看详情

Spring数据JPA和可以为空的参数

】Spring数据JPA和可以为空的参数【英文标题】:SpringdataJPAandparametersthatcanbenull【发布时间】:2015-07-2500:23:06【问题描述】:我的理解是,使用SpringdataJPA,我无法使用查询方法来获取列等于给定非空方法参数的所有行,并使用相... 查看详情

必须初始化不可为空的实例字段“_localizedStrings”

】必须初始化不可为空的实例字段“_localizedStrings”【英文标题】:Non-nullableinstancefield\'_localizedStrings\'mustbeinitialized【发布时间】:2021-10-1112:03:43【问题描述】:说实话,我以前没有遇到过这种错误。我正在关注您可以在此处看... 查看详情