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;
相關文章
相關標籤/搜索