C# 空合并操做符(??)不可重载?其实有黑科技能够间接重载!

 

?? 操做符叫作 null-coalescing operator,即 null 合并运算符。若是此运算符的左操做数不为 null,则此运算符将返回左操做数;不然返回右操做数。html

在微软的官方 C# 文档中,此操做符被定义为不可重载。不过咱们有方法能够间接实现这样的重载。express


 

 

运算符重载

你能够阅读 C# 中那些能够被重载的操做符,以及使用它们的那些丧心病狂的语法糖 了解 C# 中提供的全部能够重载的操做符。在此文中,?? 被明肯定义为不可重载。编程

你更能够在微软官方文档中找到这样的说法:ide

=, ., ?:, ??, ->, =>, f(x), as, checked, unchecked, default, delegate, is, new, sizeof, typeof
These operators cannot be overloaded.
这些运算符没法进行重载。函数

编写 NullableString 的 ?? 重载

咱们先写一个空壳子。连构造函数都是 private 的,这个类固然几乎不可用啦。post

特别注意,咱们的 Walterlv.NullableString 用的是 struct 类型,这样能与 Nullable<T> 的用法上接近。也就是说,咱们能够确保其值实际上永不为 null。ui

namespace Walterlv { public struct NullableString { private readonly string _value; private NullableString(string value) { _value = value; } } } namespace Walterlv { public struct NullableString { private readonly string _value; private NullableString(string value) { _value = value; } } }

如今咱们挑战一下官方说好了不能重载的 ?? 重载(做死):spa

![试着重载 ??]](https://img-blog.csdn.net/20180926211208502?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dQd2FsdGVy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
▲ 试着重载 ??.net

很明显,既不是可重载的一员运算符也不是可重载的二元运算符。code

如今咱们试试隐式转换:

public static implicit operator NullableString(string value) { return new NullableString(value); } public static implicit operator string(NullableString nullableString) { return nullableString._value; } 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; } 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; } 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; } } } 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(); NullableString? value = ""; var value0 = value?.ToString(); var value1 = value.ToString();

你以为 value0value1 分别会获得什么呢?





呃……

value0 获得 null,而 value1 获得 ""

另外,若是你将一开始的初始值设为 null,那又能够获得什么结果呢?

NullableString? value = null; var value0 = value?.ToString(); var value1 = value.ToString(); NullableString? value = null; var value0 = value?.ToString(); var value1 = value.ToString();

同样的,value0 获得 null,而 value1 获得 ""

另外,你能够从 null 强转出你须要的类:

var value = (NullableString?) null; var value = (NullableString?) null;
相关文章
相关标签/搜索