【问题标题】:How to get File.OpenText to return non-nullable StreamReader如何让 File.OpenText 返回不可为空的 StreamReader
【发布时间】:2020-07-20 03:21:17
【问题描述】:

考虑以下几点:

var lines = new List<string>();
string path = "FileName.txt";
var reader = File.OpenText(path);
while (!reader.EndOfStream)
{
    lines.Add(reader.ReadLine());
}

Nullable 标志设置为enable 时,在csproj 中,readerStreamReader?,它会给出Possible null reference argument for parameter 'item' 编译器警告。即使我将reader 明确设置为StreamReader,问题仍然存在。

有没有办法绕过这个警告而不关闭Nullable

【问题讨论】:

  • File.OpenText() 将始终返回 StreamReader 的实例或抛出,它永远不会返回 null

标签: c# c#-8.0 nullable-reference-types


【解决方案1】:

我相信,问题描述中包含的警告并不完整。我重现了这个问题并得到了下一个编译器警告:CS8604 Possible null reference argument for parameter 'item' in 'void List&lt;string&gt;.Add(string item)。警告出现在下一行

lines.Add(reader.ReadLine());

因为List&lt;string&gt; lines 是一个不可为空的string 值的列表,而StreamReader.ReadLine() 方法可以返回可空的string?(参见reference source)。因此,在上面的代码行中,这些尝试将 null 字符串值添加到不可为空的字符串列表中。

要解决此问题,您可以使用以下任一方法:

  • Use null-forgiving operator. 你肯定知道表达式reader.ReadLine() 的结果不可能是null,因为它是在流结束时执行的还没到。因此,您可以使用 null-forgiving 运算符来抑制警告:

    lines.Add(reader.ReadLine()!);
    
  • 检查表达式reader.ReadLine() 的结果是否为空。如果您使用下一个代码,警告将消失:

    string? line = reader.ReadLine();
    if (line != null)
        lines.Add(line);
    

更新

正如@IanRingrose 在评论中指出的那样,可以在循环中使用条件line != null,而不是条件!reader.EndOfStream()。使用这样的条件解决方案可以更清楚:

string? line;

while ((line = reader.ReadLine()) != null)
{
    lines.Add(line);
}

现在我们不需要在循环体中使用 null-forgiving 运算符或附加条件。

【讨论】:

    【解决方案2】:

    您可以将所有代码减少到仅两个对 Nullable 友好的行:

    string path = "FileName.txt";
    var lines = File.ReadLines(path).ToList();
    

    【讨论】:

      【解决方案3】:

      回答您关于读者本身可空性的具体问题:readerStreamReader?,因为 NRT 决定使用 var 将推断变量的类型为 可空 em>。

      看到这个section of the spec:

      可为空的隐式类型局部变量

      var 推断引用类型的注释类型。例如,在var s = ""; 中,var 被推断为string?

      language design notes 解释了这个决定。最终他们得出结论:

      使var 具有可以为空的注释类型并正常推断流类型。

      这个想法是因为没有var? 的语法,所以类型被推断为最不严格的(即,允许稍后将null 分配给变量)。最终,应通过流分析跟踪可空性

      也就是说,已知使用OpenText 总是返回一个非null 对象(否则它会抛出)并且有一个non-nullable return type。要消除您的问题,只需将您的变量直接声明为StreamReader

      StreamReader reader = File.OpenText(path);
      

      正如其他答案所指出的,我认为您对实际错误及其发生位置感到困惑。唯一会出现“项目”的地方是调用List&lt;&gt;.Add 时。当然,这是因为StreamReader.ReadLine 可以返回null,而您的列表声明为List&lt;string&gt; 而不是List&lt;string?&gt;

      您的选择是:

      • 更改列表的类型(可能不会)
      • 使用 null-forgiving 运算符 reader.ReadLine()!(可能,但前提是保证)
      • 使用局部变量并在添加到列表之前添加对 null 的检查(直接或通过修改循环条件以执行赋值和空值检查)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-30
        • 2018-03-18
        • 2020-09-16
        • 1970-01-01
        • 1970-01-01
        • 2018-01-28
        • 2022-11-04
        • 2016-10-29
        相关资源
        最近更新 更多