Null 条件运算符,方法为 Nullable 结构的 .Value

Null Conditional Operator with method .Value from Nullable structure

我正在尝试学习 null 条件运算符。从我了解到的书中,例如,如果我将 string[] 数组传递给方法,我可以不使用条件范围,而是使用 null 条件运算符来检查传递的 string[] 数组是否不为 null,因为例如在方法中我想要使用 .Length 属性 如果我将 null 传递给它,它将导致运行时错误。

所有这些我都明白,但是当我想将它与通用 Nullable 结构中的 nullable int 和 .Value 属性 一起使用时,它已经向我抛出编译器错误。

我想问题是,我不明白这个 '?' 到底是什么意思在后缀变量为 null 之后执行。我认为它只是跳过 属性 或它后面的方法,但也许它传递了那个 null 并只是隐藏了异常。我真的不知道,所以我想更深入地问一下这个空条件运算符到底在做什么,为什么这个可为空的 int 示例会导致错误。

错误代码:

 class Program
{
    static void Main(string[] args)
    {
        string text = null;
        Console.WriteLine("Variable contains: {0}", text?.Length); //All OK

        int? nullableInt = null;
        Console.WriteLine("Variable contains: {0}", nullableInt?.Value); //Compiler error

        Console.ReadLine();
    }
}

编辑: 编译器错误信息:

'int' 不包含 'Value' 的定义并且没有扩展方法 'Value' 可以找到接受类型 'int' 的第一个参数(您是否缺少使用指令或程序集引用?)

编辑2: 此 post 与以下内容重复: 但是,我无法从这个 post 中理解问题,但由于来自@adjan 的 post,我设法解决了这个问题 他解释得很好,但在我尝试学习它的过程中,我为稍后会阅读这篇文章的人以及可能与我处于相同位置的人做了一个更好的解释。

如果您在可空类型上使用“?”运算符,例如 int?.Member(Member - 某些方法,属性...),如果变量为 null,它会跳过成员,但如果它具有例如 5 的值,然后是运算符 '?' return variable.GetValueOrDefault(),其中 return 只是 int 值。 (return Nullable 的底层类型),@adjan 说的差不多了。但我将在这里展示对我来说解释了一切的代码:

 static void Main(string[] args)
    {
        int? number = null;

        variable?.Member

        // in fact operator '?' is doing folowing:
        if (number.HasValue)
        {
            Console.WriteLine(number.GetValueOrDefault().GetType()); //System.Int32
        }
        else
        {
            Console.WriteLine(number); //null
        }
    }

可以看到 number.GetValueOrDefault() returns System.Int32 数据类型,如果要使用 .Value 属性 则必须是 Nullable 类型,并且 System .Int32 不是可为空的类型,因此它无法访问 .Value 成员。这就是它导致错误的原因。

希望对您有所帮助:) 谢谢您的回答。 :)

在您的代码中,您试图访问 nullableInt 的成员 Value,但由于该成员不存在,因此无法编译此代码。

?. 运算符是访问者。如果访问的成员存在且未设置或设置为 null,则在运行时它 return null。相比之下,标准访问器 (.) 将在这种情况下引发 Null reference exception

尝试用 nullableInt ?? 0 之类的内容替换您的代码。 ??是 null 合并运算符,将用空字符串替换 null。

可为 Null 的值类型是特殊类型。当您使用 nullableInt? 时,您的结果实际上是 int 类型,它没有 Value 属性.

空条件运算符仅对引用类型有意义,string 作为不可变引用类型的特例。

下面的代码说明了这个问题:

string[] temp = null;
int cc = -1;
if (temp == null)
{
    cc = 0;
}
else
{
    cc = temp.Count();
}

空数组 (count() = 0) 和空数组之间存在差异。

您的代码变为:

Console.WriteLine("Variable contains: {0}", args?.Count() ?? 0); //All OK
Console.WriteLine("Variable contains: {0}", nullableInt?.ToString() ?? "woops"); //now ok
nullableInt?.Something

是语法糖:

nullableInt is null ? null : nullableInt.Value.Something

因此无需将 .Value 放在那里。因为如果你这样做,你实际上是在做 nullableInt.Value.Value

想要nullableInt?.Value的等效代码是nullableInt(本身)。

另请参阅:

值类型的可空类型 T 上的 variable?.Member 实际上转换为大致类似于

的函数
if (variable.HasValue)
    return variable.GetValueOrDefault().Member;
else
    return null;

variable.GetValueOrDefault()T 类型,而不是 Nullable<T>。只有 Nullable<T> 有一个成员 Value(除非它是您自己的包含成员 Value 的结构,但是例如您的代码中的 int 没有)。