C#6.0中的Monadic null检查

时间:2015-01-13 12:11:18

标签: c# c#-6.0 null-propagation-operator

我偶然发现了一个有趣的网站,其中解决了C#6.0的一些新(提议)功能。您可以在此处阅读:Probable C# 6.0 features

我觉得特别有趣的是monadic null检查(也称为null-propagation操作符?。)。根据网站,以下声明

var bestValue = points?.FirstOrDefault()?.X ?? -1;

包含monadic null检查,目前使用这段代码实现:

if (points != null) 
{
  var next = points.FirstOrDefault();
  if (next != null && next.X != null) return next.X;
}   
return -1;

我的第一眼就是,嘿,这里写的是什么?但在看过这个“老人”之后。代码,我开始喜欢它了。

然而,我也开始提出一些问题,我想问一下。

  • 我假设这个空传播运算符是线程安全的。但这实际上是如何进行的?比赛条件会被取消还是会持续存在?
  • 此运算符如何处理泛型类型?而且,它如何处理无约束的泛型类型?例如,考虑

    var resultAfterNullCheck = x?.Y;
    

    如果这里的类型Y用引用类型,非可空值类型和可空值类型实例化,那么没有任何合理的事情可做(因为我不知道该怎么做,因为我根本不知道该怎么做)。那么是否会返回默认值?或者会引发错误?

  • 在查看站点提供的示例(以及我上面复制的示例)时,我假设null-propagation操作符的主要好处之一是它只会评估语句一次。然而(也许是由于我对CLR的了解不足),我很好奇它是如何进行的 对我来说,第一个评估(如果points等于null)应该触发扩展方法FirstOrDefault()在点不为空时触发,然后将返回类型的evalation设置为null,否则为X,X将被退回。那么这些实际上是三个评估合二为一?或者我不正确地理解它?这会影响执行速度吗?

换句话说,什么会更快,执行空检查的旧方法,或这个新的可爱运算符?一旦Visual Studio 2015的下载完成,我将尝试通过执行一些研究来检查这一点...但这需要一点耐心......

对这种新的操作员类型有什么想法吗?它真的还是一个提议的,或者我们真的可以期待使用这个新的monadic null检查吗?

修改
正如Matthew Watson提供了一个很好的MSDN article讨论这个(以及更多)主题,我很好奇它是否提到了我之前关于无约束泛型的问题以及这个算子如何处理它。不幸的是,我还没有找到答案。虽然我认为程序员应该试图阻止使用无约束泛型,但我仍然可以想象这有时是不可行的。如果是这样的话,重新设计真的有必要吗?

3 个答案:

答案 0 :(得分:14)

你是在暗示这一点。一个接一个,你的问题:

  1. 为什么你认为它的线程安全?调用成员函数不是。这只是通过预检查空值来调用成员函数,因此您只能获得与原始函数保证一样多的线程安全性。

  2. 如果您的泛型类型允许空比较(这是此操作符将在幕后使用),那么将发出代码。如果不是,您将收到编译错误(例如,如果您要求类型为值类型)。这涵盖了所有情况!

  3. 每个运算符调用一次,就像普通的.运算符一样。如果你说A.b.c它仍然是两个级别的间接,并且使用这个新的运算符没什么不同,它只是检查空值。

  4. ?.的真正好处在于它的语义(您可以一目了然地告诉您的代码尝试做什么)和短路(使代码比嵌套if更短)。您不会使用.替换旧代码中的每个?.,实际上您可能很少使用它。但有些情况下它会很有用,例如在...OrDefault()操作之后的Linq表达式或调用事件。

答案 1 :(得分:6)

根据John Skeet on his blog,要部分回答您的第一个问题,空条件运算符?.(= null传播运算符)是线程安全的。

答案 2 :(得分:1)

您可以在Roslyn项目讨论中找到有关计划功能的所有信息。你也可以尝试使用Roslyn的控制台应用程序的新功能,如nuget-package(这意味着它可以与Visual Studio 2013一起使用)