C# 空合并操作符(??)不可重载?其实有黑科技可以间接重载!
?? 操作符叫做 null-coalescing operator,即 null 合并运算符。如果此运算符的左操作数不为 null,则此运算符将返回左操作数;否则返回右操作数。
在微软的官方 C# 文档中,此操作符被定义为不可重载。不过我们有方法可以间接实现这样的重载。
运算符重载
你可以阅读 C# 中那些可以被重载的操作符,以及使用它们的那些丧心病狂的语法糖 了解 C# 中提供的所有可以重载的操作符。在此文中,?? 被明确定义为不可重载。
你更可以在微软官方文档中找到这样的说法:
=, ., ?:, ??, ->, =>, f(x), as, checked, unchecked, default, delegate, is, new, sizeof, typeof
These operators cannot be overloaded.
这些运算符无法进行重载。
编写 NullableString 的 ?? 重载
我们先写一个空壳子。连构造函数都是 private 的,这个类当然几乎不可用啦。
特别注意,我们的 Walterlv.NullableString 用的是 struct 类型,这样能与 Nullable<T> 的用法上接近。也就是说,我们可以确保其值实际上永不为 null。
namespace Walterlv
{
public struct NullableString
{
private readonly string _value;
private NullableString(string value)
{
_value = value;
}
}
}
现在我们挑战一下官方说好了不能重载的 ?? 重载(作死):
![试着重载 ??]](https://img-blog.csdn.net/20180926211208502?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dQd2FsdGVy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
▲ 试着重载 ??
很明显,既不是可重载的一员运算符也不是可重载的二元运算符。
现在我们试试隐式转换:
public static implicit operator NullableString(string value)
{
return new NullableString(value);
}
public static implicit operator string(NullableString nullableString)
{
return nullableString._value;
}
然而这样的写法实际上并无实际用途。
但是,我们可以在 NullableString 后面加上 ?:
public static implicit operator NullableString?(string value)
{
return string.IsNullOrEmpty(value) ? (NullableString?) null : new NullableString(value);
}
public static implicit operator string(NullableString? nullableString)
{
return nullableString?.ToString() ?? string.Empty;
}
也就是说,C# 竟然允许隐式转换的时候,参数和返回值都不是此类型。当然,实际上这只对 Nullable<T> 生效,如果你试图写别的类型,是不可以的。
为了方便,我们重写一下 ToString(),部分场景下可以代替隐式转换,少写一些代码。
public override string ToString()
{
return string.IsNullOrEmpty(_value) ? string.Empty : _value;
}
于是,我们的 NullableString 类型的完整代码如下:
namespace Walterlv
{
public readonly struct NullableString
{
private readonly string _value;
private NullableString(string value)
{
_value = value;
}
public static implicit operator NullableString?(string value)
{
return string.IsNullOrEmpty(value) ? (NullableString?) null : new NullableString(value);
}
public static implicit operator string(NullableString? nullableString)
{
return nullableString?.ToString() ?? string.Empty;
}
public override string ToString()
{
return string.IsNullOrEmpty(_value) ? string.Empty : _value;
}
}
}
注释就你自己添加吧。
一些注意事项
这里有一些好玩的事情需要分享。比如我们写出如下代码:
NullableString? value = "";
var value0 = value?.ToString();
var value1 = value.ToString();
你觉得 value0 和 value1 分别会得到什么呢?
呃……
value0 得到 null,而 value1 得到 ""。
另外,如果你将一开始的初始值设为 null,那又可以得到什么结果呢?
NullableString? value = null;
var value0 = value?.ToString();
var value1 = value.ToString();
一样的,value0 得到 null,而 value1 得到 ""。
另外,你可以从 null 强转出你需要的类:
var value = (NullableString?) null;
C# 空合并操作符(??)不可重载?其实有黑科技可以间接重载!的更多相关文章
- 30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
一:值类型/引用类型的区别 值类型主要包括简单类型,枚举类型,和结构体类型等,值类型的实例通常被分配在线程堆栈上面变量保存的内容是实例数据本身.引用类型被分配在托管堆上,变量保存的是地址.引 ...
- 空合并操作符??(C#)
??二元操作符在对first??second求值时,大致会经历以下步骤: 1)对first进行求值: 2)如果结果非空,则该结果就是整个表达式的结果: 3)否则求second的值,其结果作为整个表达式 ...
- C# 的可空合并运算符(??)到底是怎样的宝宝?
前言废语 也怪自己小白和不勤奋,没有系统的学习C#相关的东西,工作一年多还是初级小菜,深感不安,来到园子才发现好多钻研技术的人,也渐渐发现自己开始喜欢上了这个编程的世界.今日偶遇??操作符,发现我只看 ...
- PHP——??空合并运算符和?:三元运算符
前言 在上一篇随笔,用三元运算符简单写的一个东西,引发了对他的兴趣,所以打算研究下. PHP7的新特性: https://php.net/manual/zh/migration70.new-featu ...
- C# 空合并运算符 ??
C#语言中,??运算符称为空合并运算符: a??b形式的空合并表达式要求a为可以为null的类型或引用类型.如果a为非null,则a??b的结果为a:否则,结果为b.仅当a为null时,该操作才计算b ...
- .net 空接合操作符 ??
C# 提供了一个所谓的 ”空接合操作符“ - 即??操作符,他要获取两个操作数. 假如左边的操作数部位null,就返回这个操作数.如果左边的操作数为null就返回右边. 空接合操作符一个妙处在于,它既 ...
- RxJava2实战---第七章 合并操作符和连接操作符
RxJava2实战---第七章 合并操作符和连接操作符 RxJava的合并操作符: startWith():在数据序列的开头增加一项数据. merge:将多个Observable合并为一个. merg ...
- NULL合并操作符??
参考官方手册: /** * NULL合并操作符 ?? */ // $a, $b, $c都未声明和定义 var_dump($a??$b??$c); // NULL // $a为数组,$b为100,$c为 ...
- C++ 函数重载,函数模板和函数模板重载,选择哪一个?
重载解析 在C++中,对于函数重载.函数模板和函数模板重载,C++需要有一个良好的策略,去选择调用哪一个函数定义(尤其是多个参数时),这个过程称为重载解析. (这个过程将会非常复杂,但愿不要遇到一定要 ...
随机推荐
- IBM WebSphere MQ for net 报错 MQRC_NOT_AUTHORIZED
最近进入新公司要维护以前的90年代的老系统 用NET对IBMMQ做测试 NET 4.0 +7.5 MQ 版本 待我写好NET调用的代码后出现错误MQRC_NOT_AUTHORIZED 折腾大半天往上找 ...
- validform.js+layer.js 表单验证样式
$("#formAdd").Validform({ tiptype: function (msg, o, cssctl) { if (o.type == 3) {//失败 laye ...
- VS2010/MFC编程入门之二十一(常用控件:编辑框Edit Control)
鸡啄米上一节讲了静态文本框,本节要讲的编辑框(Edit Control)同样是一种很常用的控件,我们可以在编辑框中输入并编辑文本.在前面加法计算器的例子中已经演示了编辑框的基本应用.下面具体讲解编辑框 ...
- 23TCP通信
.pro 文件中加入:QT+=network 在Qt中实现TCP/IP服务器端通信的流程: 1.创建监听套接字,QTcpServer 2.将监听套接字设置为监听模式, listen 3.等待并接受客户 ...
- JAVA构建高并发商城秒杀系统——架构分析
面试场景 我们打算组织一个并发一万人的秒杀活动,1元秒杀100个二手元牙刷,你给我说说解决方案. 秒杀/抢购业务场景 商品秒杀.商品抢购.群红包.抢优惠劵.抽奖....... 秒杀/抢购业务特点 秒杀 ...
- 报错org.openqa.selenium.WebDriverException: disconnected: unable to connect to renderer解决方法
做自动化时经常会遇到不兼容的问题,比如以下简单的脚本,主要是打开浏览器,然后最大化窗口,打开百度,输入内容搜索,代码如下: package com.gs.selenium; import org.op ...
- 解决android studio 模拟器取法启动声音的错误
Emulator: dsound: Reason: No sound driver is available https://jingyan.baidu.com/article/a65957f4348 ...
- python基础之多线程锁机制
GIL(全局解释器锁) GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念,是为了实现不同线程对共享资源访问的互斥,才引入了GIL 在Cpython解释器 ...
- Win7系统(台式机)设置系统的窗口背景色(豆沙绿色)
Win7系统(台式机)设置系统的窗口背景色(豆沙绿色) 1,桌面->右键->个性化->窗口颜色->高级外观设置->项目选择(窗口).颜色1(L)选择(其它)将色调改为:8 ...
- 存储结构简明分析——DAS、NAS和SAN
存储的总体分类 主流存储结构 网络存储结构大致分为三种:直连式存储(DAS:Direct Attached Storage).存储区域网络(SAN:Storage Area Network ...