外部函数作为可空保护的可能性吗?

Hof*_*ffs 5 c# .net-core c#-8.0 nullable-reference-types

C# 8 引入了可为空引用类型,这是一个非常酷的特性。现在,如果您希望获得可空值,则必须编写所谓的守卫:

object? value = null;
if (value is null)
{
  throw new ArgumentNullException();
}
…
Run Code Online (Sandbox Code Playgroud)

这些可能有点重复。我想知道是否有可能避免为每个变量编写这种类型的代码,而是有一个保护类型的static void函数,如果 value is 则抛出异常,null或者如果 value is not 则返回null。或者这对编译器来说太难推断了?特别是如果它是外部库/包?

can*_*on7 6

您可以做一些事情。

您可以[DoesNotReturnIf(...)]在您的守卫方法中使用,以指示它在特定条件为真或假时抛出,例如:

public static class Ensure
{
    public static void True([DoesNotReturnIf(false)] bool condition)
    {
        if (!condition)
        {
             throw new Exception("!!!");   
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

public void TestMethod(object? o)
{
    Ensure.True(o != null);
    Console.WriteLine(o.ToString()); // No warning
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为

[DoesNotReturnIf(bool)]: 放置在 bool 参数上。如果参数具有指定的 bool 值,则无法访问调用后的代码


或者,您可以像这样声明一个保护方法:

public static class Ensure
{
    public static void NotNull([NotNull] object? o)
    {
        if (o is null)   
        {
            throw new Exception("!!!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

public void TestMethod(object? o)
{
    Ensure.NotNull(o);
    Console.WriteLine(o.ToString()); // No warning
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为

[NotNull]:? 对于输出(引用/输出参数,返回值),即使类型允许,输出也不会为空。对于输入(按值/输入参数),当我们返回时,已知传递的值不是空的。

SharpLab 示例


当然,真正的问题是你为什么要这样做。如果您不希望value成为null,则将其声明为object?,而不是object- 这就是拥有 NRT 的意义所在。