What is it? Here’s the scenario


Consider getting the grandchild of a parent object like this:

var g1 = parent.child.child.child;

很明显parent类里面有一个child类的成员,child类又包含child类的成员,这是一个递归调用,child.child.child....可以延伸到无限级。

Okay, so, this is some poor coding because the value of child could be null. If I attempt to ask for the value of child and the containing object is null, a NullReferenceException will be raised and my app will crash.

Here’s what I mean. Consider this:

var g1 = [parent].[child].[null].child;

In this case, I was lucky enough to get two levels in before I hit a null object. But I did hit a null object, and as a result the runtime will thrown an exception.

Instead, you might add some error checking and do this:

// variation 1
var item = this.Parent;
item = (item == null) ? null : item.child;
item = (item == null) ? null : item.child;
var g1 = (parent == null) ? null : item.child;
if (g1 != null) // TODO
 
// variation 2
var g1 = (Child)null;
var item = this.Parent;
if (item != null)
{
item = item.Child;
if (item != null)
{
item = item.Child;
if (item != null)
{
g1 = item.Child;
}
}
}
if (g1 != null) // TODO

Good. Now, this is safe and effective coding. The sample above shows two of many potential approaches. The first using the ternary(三元的) operator in C#, the second using simple conditional blocks.  As we know, we cannot ask for a child property from an object that is null. So, we must check each level.

The conditional code is not difficult to write, but it certainly impacts the size of your code, the complexity of your code, and the readability of your code. Having said that, it’s what we all do today. Code like this shows up all the time and there is nothing wrong with that; but, what if there were a better way.

How the new operator works


Consider getting the grandchild of a parent object like this:

var g1 = parent?.child?.child?.child;
if (g1 != null) // TODO

Wow! That’s the equivalent of testing every single level, but in a single line of code. The “?.” operator is basically saying, if the object to the left is not null, then fetch what is to the right, otherwise return null and halt the access chain.

It’s a wonderful addition to the language’s syntax.

Furthermore


Mad’s Visual Studio User Voice comment continued with a little more explanation of the operator’s implementation. He said, “If the type of e.x (etc) is a non-nullable value type S, then the type of e?.x is S?. Otherwise the type of e?.x is the same as that of e.×. If we can’t tell whether the type is a non-nullable value type (because it is a type parameter without sufficient constraints) we’ll probably give a compile-time error.” This comment, and the idea that a method call or indexer can be to the right of the operator are just candy.

> Now, let’s add NonNullable reference types and we’re really cooking.

此外如果使用!运算符声明类为NonNullable类型,再使用?.运算符时会导致编译错误,如下所示:

public void DoSomething(Order! order)
{
Customer customer = order?.Customer; // Compiler error: order can’t be null
}

因为这时order对象永远不可能为null,C#编译器认为在order后使用?.是多此一举

原文链接

C# 6.0 的?.运算符的更多相关文章

  1. php7.0 新增运算符??

    ??是php7 新增符号 其作用近似于三目运算符 ?: 但存在着细微差别 比较示例代码如图:         $b = $a?$a:2; 三目运算 <=>     $e = $a??'ho ...

  2. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  3. Swift3.0变化分享

    Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...

  4. swift3.0变化总结

    Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...

  5. 窥探Swift之需要注意的基本运算符和高级运算符

    之前更新了一段时间有关Swift语言的博客,连续更新了有6.7篇的样子.期间间更新了一些iOS开发中SQLite.CollectionViewController以及ReactiveCocoa的一些东 ...

  6. Swift2.3 --> Swift3.0 的变化

    Swift3.0语法变化 首先和大家分享一下学习新语法的技巧: 用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Synt ...

  7. swift学习笔记之-高级运算符

    //高级运算符 import UIKit /*高级运算符(Advanced Operators):位运算符.溢出运算符.优先级和结合性.运算符函数.自定义运算符 位运算符: 1.位运算符可以操作数据结 ...

  8. C 运算符优先级

    优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右   () 圆括号 (表达式)/函数名(形参表)   . 成员选择(对象) 对象.成员名   -& ...

  9. Swift - 2.3的代码到3.0的转变

    分享一下学习新语法的技巧:用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Syntax- 让Xcode帮我们把Swift ...

随机推荐

  1. 二 Channel

    Java NIO的通道类似流,但又有些不同 既可以从通道中读取数据,也可以写数据到通道.但是流的读写通常是单向的 通道可以异步读写 通道中的数据通常总是要先读到一个Buffer,或者总是从Buffer ...

  2. 为什么分布式一定要有redis?(转)

    为什么分布式一定要有redis? 程序员小灰 6天前 点击上方“程序员小灰”,选择“置顶公众号” 有趣有内涵的文章第一时间送达! 作者:孤独烟 来自:http://rjzheng.cnblogs.co ...

  3. hive配置参数的说明:

    hive.ddl.output.format:hive的ddl语句的输出格式,默认是text,纯文本,还有json格式,这个是0.90以后才出的新配置: hive.exec.script.wrappe ...

  4. C++教程|菜鸟教程

    https://www.runoob.com/cplusplus/cpp-tutorial.html 在线编辑器 http://www.runoob.com/try/runcode.php?filen ...

  5. TextView的跑马灯效果(AS开发实战第二章学习笔记)

    TextView的跑马灯效果跑马灯用到的属性与方法说明singleLine 指定文本是否单行显示ellipsize 指定文本超出范围后的省略方式focusable 指定是否获得焦点,跑马灯效果要求设置 ...

  6. 初学js的穷举思想

    初学者,最关机键的,就是掌握for的穷举思想. 穷举:穷尽.完全.全部. 具体方法: 外层:用for循环一一列举所有可能性 内层:用if语句进行判断,如果满足条件就输出,不满足的跳出进行下次循环. & ...

  7. linux 获取当前程序路径

    const std::string strCfgName = "logger_import_db.conf" ;bool fGetCfgFileName(std::string&a ...

  8. Porting QML Applications to Qt 5

    When porting QML-related code from Qt 4.8 to Qt 5, application developers should be aware that the Q ...

  9. Process.start: how to get the output?

    1: Synchronous example static void runCommand() { Process process = new Process(); process.StartInfo ...

  10. PowerShell管理Hyper-V(Windows2008R2)

    gwmi -list -namespace "root\virtualization" 在Windows2012R2之前的版本,Hyper-V管理都是用的root\virtuali ...