Phi*_*tle 19 c# null language-features c#-6.0
该空传播运营商/条件接入表达在未来的C#-6.0看起来像一个非常方便的功能.但我很好奇它是否有助于解决检查子成员是否为null然后在if块内的所述子成员上调用布尔方法的问题:
public class Container<int>{
IEnumerable<int> Objects {get;set;}
}
public Container BuildContainer()
{
var c = new Container();
if (/* Some Random Condition */)
c.Objects = new List<int>{1,2,4};
}
public void Test()
{
var c = BuildContainer();
//Old way
if ( null != c && null != c.Objects && c.Objects.Any())
Console.Write("Container has items!");
//C# 6 way?
if (c?.Object?.Any())
Console.Write("Container has items!");
}
Run Code Online (Sandbox Code Playgroud)
会c?.Object?.Any()
编译吗?如果传播运算符短路(我认为这是正确的术语)为null,那么你有if (null)
,这是无效的.
C#团队是否会解决这个问题,或者我是否错过了null传播运算符的预期用例?
Eld*_*iev 42
它不会这样工作.您可以跳过说明并查看下面的代码:)
如您所知,?.
如果子成员为null,则运算符将返回null.但是,如果我们试图获得一个不可为空的成员,比如Any()
返回的方法,会发生bool
什么?答案是编译器将"包装"一个返回值Nullable<>
.例如,Object?.Any()
将给我们bool?
(这是Nullable<bool>
),而不是bool
.
唯一不允许我们在if
语句中使用这个表达式的是它不能被隐式地转换为bool
.但你可以明确地进行比较,我更喜欢比较true
这样:
if (c?.Object?.Any() == true)
Console.Write("Container has items!");
Run Code Online (Sandbox Code Playgroud)
感谢@DaveSexton还有另一种方式:
if (c?.Object?.Any() ?? false)
Console.Write("Container has items!");
Run Code Online (Sandbox Code Playgroud)
但至于我,比较true
似乎更自然:)
空条件运算符将返回null
或表达式结尾处的值.对于值类型它将返回结果Nullable<T>
,因此在您的情况下它将是Nullabe<bool>
.如果我们查看C#中即将发布的功能 文档中的示例(此处指定),它有一个示例:
int? first = customers?[0].Orders.Count();
Run Code Online (Sandbox Code Playgroud)
在上面的例子中int
,Nullable<int>
将返回而不是.因为bool
它会回来Nullable<bool>
.
如果您在Visual Studio"14"CTP中尝试以下代码:
Nullable<bool> ifExist = c?.Objects?.Any();
Run Code Online (Sandbox Code Playgroud)
上述行的结果将是Nullable<bool>
/ bool?
.之后您可以进行比较,例如:
if (c?.Object?.Any() ?? false)
Run Code Online (Sandbox Code Playgroud)
使用Nullable<T>.GetValueOrDefault
方法
if ((c?.Objects?.Any()).GetValueOrDefault())
Run Code Online (Sandbox Code Playgroud)
使用比较 true
if (c?.Objects?.Any() == true)
Run Code Online (Sandbox Code Playgroud)