【问题标题】:The "out" keyword of C# 8 doesn't pass "System.Diagnostics.CodeAnalysis" rules?C# 8 的“out”关键字没有通过“System.Diagnostics.CodeAnalysis”规则?
【发布时间】:2020-03-06 14:35:25
【问题描述】:

我正在将一些代码从 C#5 转换为 C#8,在编译规则集中启用可空检查,

<Nullable>enable</Nullable>

然后我遇到了这样的问题:

class Person
{
    public int MI { get; set; } = 3;
}
class UseWeakReference
{
    public static void Main(string [] args)
    {
        Person person = new Person();
        WeakReference<Person> wr = new WeakReference<Person>(person);

        wr.TryGetTarget(out Person p1); // doesn't compile
        Console.WriteLine(p1);
    }
}

编译错误为:

CS8600: Converting null literal or possible null value to non-nullable type.

这个编译错误的真正原因是什么,以及如何解决它?

【问题讨论】:

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


【解决方案1】:

您可以允许out 参数成为可能的空引用,并在方法调用后将其与null 值进行比较

wr.TryGetTarget(out Person? p1);
if (p1 != null)
    Console.WriteLine(p1);

或者直接查看TryGetTarget方法的返回结果:当为true时,p1不能为null

var result = wr.TryGetTarget(out Person? p1);
if (result)
    Console.WriteLine(p1);

编译器警告的原因是TryGetTarget是这样实现的

public bool TryGetTarget([MaybeNullWhen(false), NotNullWhen(true)] out T target)
{
    // Call the worker method that has more performant but less user friendly signature.
    T o = this.Target;
    target = o!;
    return o != null;
}

out参数的可空性根据返回值确定,根据[MaybeNullWhen(false), NotNullWhen(true)]属性,不能在编译时确定,只能在运行时确定。

当您将它分配给不可为空的引用时,编译器会警告您可能出现的问题。检查返回结果或使用Person?在这里似乎是一个合适的解决方案

【讨论】:

    【解决方案2】:

    无法保证p1 在方法返回时不会为空。但是TryGetValue被注释说如果它返回true那么out参数不会是null,所以你的代码写成:

    if(wr.TryGetTarget(out var p1))
    {
        Console.WriteLine(p1);
    }
    

    p1 将具有Person? 类型,但编译器将进行流分析以显示TryGetTarget 返回true 它知道p1 不是null 并且可以被视为Person .

    【讨论】:

      猜你喜欢
      • 2020-04-23
      • 2019-01-16
      • 2011-02-17
      • 1970-01-01
      • 2011-12-04
      • 2011-01-01
      • 2018-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多