2017-06-18 30 views
1

我想了解空条件运算符。从书中我学到了,例如,如果我将string []数组传递给方法,我可以不使用条件作用域,而使用null条件运算符来检查传递的字符串[]数组是否为空,因为例如在方法中,我会希望使用.Length属性,如果我将null传递给它,它将导致运行时错误。空条件运算符与方法.Value可空结构

所有这一切我明白,但是当我想用泛型Nullable结构中的可为null的int和.Value属性来使用它时,它已经向我抛出了编译器错误。

我想问题会是,我不明白这是什么'?'在后缀变量之后做空。我认为它只是跳过它后面的属性或方法,但它可能会传递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(); 
    } 
} 

编辑: CompilerError消息:

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

编辑2: 这篇文章是重复的: null conditional operator not working with nullable types? 但是我无法从这篇文章理解的问题,但我设法得到它从感谢@adjan https://stackoverflow.com/a/44613674/7477611 张贴在那里,他解释得很好,但在我的努力procces学习它,我为稍后阅读此文的人提供了一个更好的解释,也许对于那些与我处于同一位置的人有更好的解释。如果在可空类型上使用'?'运算符,例如int?.Member(Member - 某个方法,属性...),那么如果变量为null,它将跳过成员,但是如果它具有例如5 ,那么运算符'?'返回variable.GetValueOrDefault(),它只返回int值。 (返回基本类型的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()返回System.Int32数据类型,如果你想使用.Value属性它必须是空类型,并且System.Int32不是可以为空的类型,因此它没有访问.Value成员。这就是它导致错误的原因。

希望它有帮助:) 谢谢你的回答。 :)

+0

你应该总是在你的问题中包含完整的错误信息 – UnholySheep

+3

[null条件运算符不可用于可空类型?](https://stackoverflow.com/questions/31811392/null-conditional-operator-not-使用可空类型) – mjwills

回答

5

上的空类型值类型Tvariable?.Member实际上转换到一个功能大致是

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

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

+0

是的,记住这个东西只是一个语法糖,并且看看它实际生成的代码总是很好。 –

0

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

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

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

+0

@mjwills是的,它是'nullableInt? 0',因为它是一个int值。或'nullableInt?.ToString()??“”''如果你想要一个字符串 – Jimbot

+0

它会引发一个错误,你必须做'nullableInt?.ToString()'所以它返回null。 – Jimbot

+0

是的只是尝试它:'int? nullableInt = null; Console.WriteLine(“Variable contains:{0}”,nullableInt?.ToString()??“this is null”);' – Jimbot

0

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

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

+0

为什么?你可以有一个可为空的结构体,并为结构体的成员使用空值条件运算符。 – Adrian

+0

谢谢,还有一个问题,这是什么结果的int类型与nullableInt? –

+0

@adjan真的,我忘了结构。是的,尽管我会避免可空结构,你是对的。 –

0

下面的代码说明了此问题:

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

有一个空的阵列之间的差(计数()= 0)和阵列,其为空。

您的代码就变成了:

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

是语法糖:

nullableInt is null ? null : nullableInt.Value.Something 

因此没有必要把.value的存在。因为如果你这样做,你是切实做好nullableInt.Value.Value

等效代码什么通过nullableInt?.Value要的是nullableInt(本身)。

参见:

null conditional operator not working with nullable types?