在不使用抑制字符的情况下,如何避免从文件中读取一行文本时出现空警告?

How can I avoid a null warning when reading a line of text from a file, without using a supression character?

提问人:russ 提问时间:6/30/2023 最后编辑:Mustafa Özçetinruss 更新时间:7/15/2023 访问量:104

问:

我最近使用 创建了一个新的 Windows 窗体项目。NET6 - 并收到很多“空”警告(例如)。从我发现的其他帖子中,我看到我可以通过同时禁用可为 null 的警告或在适当的位置添加问号和感叹号来消除警告。这两个选项似乎只是掩盖了潜在的问题,我想知道以下代码示例是否有更好的解决方案。CS8600: Converting null literal or possible null value to non-nullable type.

String LineText, filename, bin, binname;
String[] codes;

InkFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (InkFileDialog.ShowDialog() == DialogResult.OK)
{
    StreamReader inkfile = new StreamReader(InkFileDialog.FileName);
    while ((LineText = inkfile.ReadLine()) != null)
    {
    }

在第一个示例的 while 语句中,“inkfile.ReadLine()“给出 CS8600 警告(如上所述)。

String LineText, filename, bin, binname;
String[] codes;

InkFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (InkFileDialog.ShowDialog() == DialogResult.OK)
{
    StreamReader inkfile = new StreamReader(InkFileDialog.FileName);
    if (inkfile.EndOfStream)
    {
        MessageBox.Show("Ink file is empty.");
        return;
    }
    else
    {
        // Read header lines from the file
        while (!(LineText = inkfile.ReadLine()).Contains("RowData"))
        {

在第二个示例的语句中,给出了相同的警告,加上 .whileLineText = infile.ReadLine()CS8600CS8602: Dereference of a possibly null reference

人们提到执行 null 检查,但我无法找到使用我拥有的 while 循环来完成此操作的方法。

C# NullReferenceException

评论

0赞 Selvin 6/30/2023
你的是,在新的 C# 中意味着它不能为 null(它不是可为 null 的字符串),并且可能会重新...你不明白什么?....使 nullable 如果你 wana 分配在那里LineTextStringReadLinenullLineTextnull
0赞 Rafalon 6/30/2023
stackoverflow.com/a/71350236/7831383 可能会对您有所帮助
0赞 Andrew Morton 7/15/2023
您可以删除它 - 由于 .有些人主张不使用其他。此外,您可以将该行更改为让它自动为您处理墨水文件。elsereturnStreamReader inkfile = new StreamReader(InkFileDialog.FileName);using var inkfile = new StreamReader(InkFileDialog.FileName);
1赞 russ 7/18/2023
安德鲁,感谢您的额外提示。

答:

0赞 DisplayName 6/30/2023 #1

你怀疑一起禁用警告是正确的 - 添加这些警告是为了让您知道代码中的潜在错误,而禁用它们会隐藏这一点。Null 以及扩展的 NullReferenceException 被其创建者描述为“他的十亿美元错误”。就我个人而言,我甚至比默认设置更进一步,将警告提升为错误,以便在我解决这些问题之前不会构建我的代码,这使得 NullReferenceExceptions(几乎)不可能。

第一个示例中的问题是,您分配了一个可为 null 的类型(返回到一个不可为 null 的变量。因此,编译器将假定所有将来对 的引用也可能为 null,并且正如你所发现的那样,您将一直收到警告。ReadLine()LineTextLineText

第二个示例进一步演示了这一点,因为编译器已(正确)确定,如果返回 null,则对 的调用可能会导致 NullReferenceException。.Contains("RowData")ReadLine()

这里重要的是编译器是正确的,它会警告你代码中的潜在错误;你应该听它,并处理这些错误。一种方法是将可空性应用于相关变量。?

您还可以使用其他语言/框架功能来“教导”编译器什么是安全的。编译器在这里关注的是,您可能会尝试在 while 循环之外进行访问——在循环中,值可能永远不会为 null,但任何后续代码都不会有相同的保证。因此:LineText

  • 如果 的值只在循环内部访问,则可以将代码简化为,编译器将理解循环内部的值永远不会为 null。LineTextwhile (inkfile.ReadLine() is string lineText) { /* code accessing lineText */ }lineText
  • 同样,将对第二个示例产生相同的影响。while (inkfile.ReadLine() is string lineText && lineText.Contains("RowData")) { /* code accessing lineText */ }
  • 另一方面,如果结果将在循环之外使用,请监听编译器并应用编译器,以便它可以正确地完成其工作。LineText?

最后,避免使用 因为这会有效地禁用单个警告,并且似乎只存在于编译器无法以其他方式确信值不能为 null 的实例中。这些实例在 .NET 的每个版本中都很少见,因为添加了新功能,使可为 null 的上下文清晰!

希望这对:)有所帮助

评论

0赞 DisplayName 7/6/2023
即使您确实想在循环之外访问,它也将始终具有该点的最后一个读取行的值 - 因此您可以在循环中分配它:.LineTextLineText = lineText
1赞 russ 7/6/2023
感谢您的详细说明和示例修复。我不熟悉“is”结构 - 这成功了。
1赞 Andrew Morton 7/15/2023
对于任何将来的读者,该构造都记录在声明和类型模式中。is