C#6.0中的Monadic null检查

Rvd*_*V79 23 c# c#-6.0 null-propagation-operator

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

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

var bestValue = points?.FirstOrDefault()?.X ?? -1;
Run Code Online (Sandbox Code Playgroud)

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

if (points != null) 
{
  var next = points.FirstOrDefault();
  if (next != null && next.X != null) return next.X;
}   
return -1;
Run Code Online (Sandbox Code Playgroud)

我的第一眼就是,嘿,这里写的是什么?但在查看"旧"代码后,我开始喜欢它了.

但是,我也开始提出一些问题,我想问一下.

  • 我假设这个null传播的运算符是线程安全的.但这实际上是如何进行的?种族条件会被删除还是会持续存在?
  • 该运算符如何处理泛型类型?而且,它如何处理无约束的泛型类型?例如,考虑一下

    var resultAfterNullCheck = x?.Y;
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Bli*_*ndy 14

你是在暗示这个.你的问题一个接一个:

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

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

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

真正的好处?.是它的语义(你可以一眼就看出你的代码试图做什么)和短路(使代码比嵌套ifs 短很多).你不会.用你的旧代码替换掉每一个?.,事实上你可能很少使用它.但有些情况下它会很有用,比如在...OrDefault()操作之后的Linq表达式或调用事件.

  • 我之前听说过,我在推翻这些东西.甚至我的妻子都抱怨它.我想它有一些事情要做,我试图了解机制在实际尝试之前是如何工作的.@Rawling对我的第一个问题是正确的.我会编辑我的问题. (4认同)
  • 真的有必要吗?我认为没有人希望`x?.f`能够神奇地制作`f`线程安全.他只是问`x?.f`是否删除了`if(xf!= null)xf`中的竞争条件. (3认同)

Erw*_*yer 6

根据John Skeet在他博客上的说法,部分回答你的第一个问题,null条件运算符?.(= null传播运算符)是线程安全的.