可能重载空合并运算符?
Posted
技术标签:
【中文标题】可能重载空合并运算符?【英文标题】:Possible to overload null-coalescing operator? 【发布时间】:2010-09-25 19:57:04 【问题描述】:是否可以为 C# 中的类重载 null 合并运算符?
例如,如果实例为空,我想返回一个默认值,如果不是,则返回该实例。代码看起来像这样:
return instance ?? new MyClass("Default");
但是如果我想使用 null-coalescing 运算符来检查 MyClass.MyValue 是否已设置呢?
【问题讨论】:
Patrik,一个用途:我想重载字符串的空合并运算符以将空视为空。这是否明智或其他,这是一个不同的问题。 【参考方案1】:简单的答案:没有
C# 设计原则不允许改变语言语义的运算符重载。因此复合赋值、三元运算符、...等复杂运算符不能重载。
【讨论】:
【参考方案2】:好问题!它没有在list of overloadable and non-overloadable operators 中以一种或另一种方式列出,the operator's page 上也没有提到任何内容。
所以我尝试了以下方法:
public class TestClass
public static TestClass operator ??(TestClass test1, TestClass test2)
return test1;
我收到错误“预期可重载的二进制运算符”。所以我想说,从 .NET 3.5 开始,答案是不。
【讨论】:
只想提供一个更新:截至2019-09-10的页面日期,C#的the official documentation仍然声明不能重载。【参考方案3】:根据ECMA-334 标准,不能超载??操作员。
同样,您不能重载以下运算符:
= && || ?: ?. 已检查 未选中 新 类型 作为 是【讨论】:
【参考方案4】:如果有人在这里寻找解决方案,最接近的例子就是这样做
return instance.MyValue != null ? instance : new MyClass("Default");
【讨论】:
-1:你没有抓住重点,你已经可以用 OP 的代码做你建议的事情了......也请仔细阅读这个问题,他不是在问如何做到这一点,但如果可能的话重载空合并运算符 - 不幸的是,它不是。 我知道他问的是关于超载 ??接线员和我读了回复说这是不可能的。因此,我只是为任何可能遇到此页面并寻找可行的东西的人提供了一个可以达到预期结果的解决方案(假设它不使用 ?? 运算符)。 +1:因为它是相关的,并且清楚地表明这不是一个真正的答案,而是一个紧密的例子 @Jaap - 如果instance
为空,则会抛出 NullReferenceException。你需要它是(instance != null && instance.MyValue != null) ? instance : new MyClass("Default");
【参考方案5】:
据传这是下一版 C# 的一部分。来自http://damieng.com/blog/2013/12/09/probable-c-6-0-features-illustrated
7.一元空值检查
无需在访问属性或方法之前检查空值。在 Groovy 中称为安全导航运算符)。
之前
if (points != null)
var next = points.FirstOrDefault();
if (next != null && next.X != null) return next.X;
return -1;
之后
var bestValue = points?.FirstOrDefault()?.X ?? -1;
【讨论】:
【参考方案6】:我试图通过我编写的与Nullable<T>
非常相似的结构来实现这一点。使用Nullable<T>
,您可以执行类似的操作
Nullable<Guid> id1 = null;
Guid id2 = id1 ?? Guid.NewGuid();
将id1
从Nullable<Guid>
隐式转换为Guid
没有问题,尽管Nullable<T>
只有defines an explicit
conversion 才能键入T
。用我自己的类型做同样的事情,它给出了一个错误
运算符'??'不能应用于“MyType”类型的操作数和 '指导'
所以我认为编译器内置了一些魔法,可以为Nullable<T>
设置一个特殊例外。所以作为一种选择......
tl;博士
我们不能覆盖 ??
运算符,但是如果您希望合并运算符评估基础值而不是类(或在我的情况下为结构)本身,您可以只使用导致很少额外的方法需要击键。在我上面的案例中,它看起来像这样:
public struct MyType<T>
private bool _hasValue;
internal T _value;
public MyType(T value)
this._value = value;
this._hasValue = true;
public T Or(T altValue)
if (this._hasValue)
return this._value;
else
return altValue;
用法:
MyType<Guid> id1 = null;
Guid id2 = id1.Or(Guid.Empty);
这很好用,因为它是一个结构,id1
本身实际上不能为空。对于一个类,如果实例为空,只要您尝试检查的值是公开的,扩展方法就可以处理:
public class MyClass
public MyClass(string myValue)
MyValue = myValue;
public string MyValue get; set;
public static class MyClassExtensions
public static string Or(this MyClass myClass, string altVal)
if (myClass != null && myClass.MyValue != null)
return myClass.MyValue;
else
return altVal;
用法:
MyClass mc1 = new MyClass(null);
string requiredVal = mc1.Or("default"); //Instead of mc1 ?? "default";
【讨论】:
以上是关于可能重载空合并运算符?的主要内容,如果未能解决你的问题,请参考以下文章