C# 6.0 中的一元空检查

本文关键字:一元 检查 | 更新日期: 2023-09-27 18:37:24

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

我觉得特别有趣的是一元空检查(也称为零传播运算符根据该网站,以下声明

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;

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

但是,我也开始收到一些问题,我想问一下。

  • 我假设这个 null 传播运算符是线程安全的。但这实际上是如何执行的呢?竞争条件会被删除还是持续存在?
  • 此运算符将如何处理泛型类型?此外,它将如何处理不受约束的泛型类型?例如,考虑

    var resultAfterNullCheck = x?.Y;
    

    如果这里的类型 Y 是使用引用类型、不可为空的值类型和可为空的值类型实例化的,那么就没有什么合理的可做的(因为我想不出该怎么做,因为我根本不知道该怎么做)。那么是否有将返回的默认值?还是会抛出错误?

  • 在查看站点提供的示例(我在上面复制了该示例)时,我认为 null 传播运算符的主要好处之一是它只会计算一次语句。但是(也许是由于我对CLR缺乏了解),我对如何执行它感到非常好奇。
    对我来说,第一次评估(如果点等于 null)应该触发扩展方法 FirstOrDefault() 在点不为 null 时触发,然后返回的类型值为 null 或不为 null,否则将返回 X。所以这实际上是三个评估合并为一个?还是我理解错误?这会影响执行速度吗?

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

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

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

C# 6.0 中的一元空检查

你想太多了。一个接一个,你的问题:

  1. 为什么你会认为它是线程安全的?调用成员函数不是。这只不过是调用带有预检查 null 的成员函数,因此您只能获得原始函数保证的线程安全性。

  2. 如果您的泛型类型允许 null 比较(这是此运算符将在后台使用的内容),则将发出代码。否则,将收到编译错误(例如,如果要求类型为值类型)。这涵盖了所有情况!

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

?.的真正好处是它是语义的(你可以一目了然地知道你的代码试图做什么)和短路(使代码比嵌套的if短得多)。您不会用?.替换旧代码中的每个.,实际上您可能很少使用它。但在某些情况下,它会很有用,例如在 Linq 表达式中遵循...OrDefault()操作或调用事件。

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

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

  • 罗斯林讨论
  • 新的 C# 6.0 功能和测试控制台应用