取消引用可能为空的引用警告

Dereference of a possibly null reference warning

提问人:Totte 提问时间:2/20/2023 最后编辑:Bill Tür stands with UkraineTotte 更新时间:2/20/2023 访问量:1241

问:

我有一个名为 .conversationService

当我尝试在对象上调用方法时,我收到警告:

“conversationService”在这里可能为 null。CS8602:取消引用 可能为 null 引用。

问题是,我不认为它在那里可以是空的。我是否遗漏了什么,我怎样才能摆脱这个警告?

这是我的代码:

public string GetNextState(string input)
{
    if (conversationService == null)
        LoadConversationService();

    List<ConversationResponse> responses = conversationService.PredictResponse(new Conversation(input));
    return responses.First().Text;
}

public void LoadConversationService()
{
    conversationService = new ConversationService();
}

下图显示了带有警告的代码:

显示可能为 null 引用的取消引用警告的代码

我知道我可以把它写成

conversationService!.PredictResponse();

但我认为它引入了不应该需要的混乱。

我尝试检查空引用,然后在收到警告的代码行之前处理它。我希望它能使编译器明白,当取消引用发生时,它不能为空,但它不明白。

C# null 警告 取消引用

评论


答:

0赞 JDChris100 2/20/2023 #1

发生这种情况的原因是,初始化此类的构造函数时,conversationService 为 null。若要避免此问题,可以直接在类的构造函数中创建 conversationService 对象的实例,如下所示:


private ConversationService conversationService = new ConversationService();

public string GetNextState(string input)
{
    List<ConversationResponse> responses = conversationService.PredictResponse(new Conversation(input));
    return responses.First().Text;
}

此方法将防止发生 null 警告。

你也可以将 conversationResponse 包装在 Getter 中,例如

public string GetNextState(string input)
{
    List<ConversationResponse> responses = GetConversationService().PredictResponse(new Conversation(input));
    return responses.First().Text;
}

public ConversationService GetConversationService()
{
    if(conversationService == null) conversationService = new ConversationService();
    return conversationService();
}

或者,可以使用 null 宽恕运算符 (!) 来禁止显示这些警告,就像之前所做的那样。

评论

0赞 Totte 2/21/2023
我没有在我的问题中显示真正的代码。实际上,LoadConversationService() 不仅仅是创建一个新对象,它比这更复杂,这就是为什么我不想从构造函数调用它的原因。我希望它被延迟加载。感谢您对空宽容运算符的建议,但我想知道是否有任何方法可以避免这种情况,因为在我看来,这里不应该需要它。我不认为 conversationService 在 PredictResponse() 时可以为 null,我认为编译器应该理解这一点,但我想它没有?也许我只是错过了什么?
0赞 JDChris100 2/22/2023
我建议,如果 ConversatioinService 对象非常复杂或性能不佳,您可能应该重构它。另一种方法是,就像我说的,制作一个名为 GetConversaionService 的包装器,它加载(如果为 null)并返回 conversaion 服务
0赞 bmo 2/20/2023 #2

您正在尝试从可为 null 的对象访问方法,因此编译器会警告您 conversationService 可能为 null。您可以写信告诉编译器您期望可能为 nullconversationService?.PredictResponse(...)

评论

0赞 Totte 2/21/2023
但是当 PredictResponse() 被调用时,conversationService 不能为空吗?这只是编译器的当前状态,它不理解这一点,我必须手动告诉它它不能为空吗?