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

栏目: C# · 发布时间: 7年前

内容简介:在微软的官方 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;
        }
    }
}

现在我们挑战一下官方说好了不能重载的 ?? 重载(作死):

C# 空合并操作符(??)不可重载?其实有黑科技可以间接重载! ▲ 试着重载 ??

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

现在我们试试隐式转换:

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();

你觉得 value0value1 分别会得到什么呢?

呃……

value0 得到 null ,而 value1 得到 ""

另外,如果你将一开始的初始值设为 null ,那又可以得到什么结果呢?

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

一样的, value0 得到 null ,而 value1 得到 ""

另外,你可以从 null 强转出你需要的类:

var value = (NullableString?) null;

本文会经常更新,请阅读原文: https://walterlv.com/post/overload-null-coalescing-operator-in-csharp.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

C# 空合并操作符(??)不可重载?其实有黑科技可以间接重载! 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接:https://walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

构建之法(第三版)

构建之法(第三版)

邹欣 / 人民邮电出版社 / 2017-6 / 69.00元

软件工程牵涉的范围很广, 同时也是一般院校的同学反映比较空洞乏味的课程。 但是,软件工程 的技术对于投身 IT 产业的学生来说是非常重要的。作者有在世界一流软件企业 20 年的一线软件开 发经验,他在数所高校进行了多年的软件工程教学实践,总结出了在 16 周的时间内让同学们通过 “做 中学 (Learning By Doing)” 掌握实用的软件工程技术的教学计划,并得到高校师生的积极反馈。在此 ......一起来看看 《构建之法(第三版)》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具