代码之家  ›  专栏  ›  技术社区  ›  Troskyvs

C#8的“out”关键字没有通过“System.Diagnostics.code analysis”规则?

  •  0
  • Troskyvs  · 技术社区  · 5 年前

    我正在将一些代码从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.
    

    这个编译错误的真正原因是什么?如何修复它?

    1 回复  |  直到 4 年前
        1
  •  4
  •   Pavel Anikhouski    4 年前

    你可以允许 out 参数设置为可能的空引用,并将其与 null 方法调用后的值

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

    或者简单地检查 TryGetTarget 方法:当 true 这个 p1 不可能 无效的

    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;
    }
    

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

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

        2
  •  1
  •   Sean    5 年前

    不能保证 p1 当方法返回时,将不会为null。然而 TryGetValue 被注释为如果它返回 true 那么out参数就不会是 null ,因此,将代码编写为:

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

    p1 会有一种 Person? 但编译器将进行流分析,以显示 TryGetTarget 返回 符合事实的 它知道这一点 p1 不是 无效的 并且可以被视为 Person .