在C#中,是否可以重载空值合并运算符来处理类?例如,如果一个实例为null,则返回默认值,如果不是null,则返回该实例。代码可能如下所示:
return instance ?? new MyClass("Default");
但如果我想使用空值合并运算符来检查MyClass.MyValue是否已设置该怎么办?
在C#中,是否可以重载空值合并运算符来处理类?例如,如果一个实例为null,则返回默认值,如果不是null,则返回该实例。代码可能如下所示:
return instance ?? new MyClass("Default");
但如果我想使用空值合并运算符来检查MyClass.MyValue是否已设置该怎么办?
好问题!在可重载与不可重载运算符列表和运算符页面中都没有列出该项。所以我尝试了以下方法:
public class TestClass
{
public static TestClass operator ??(TestClass test1, TestClass test2)
{
return test1;
}
}
我得到了错误信息“期望可重载的二元操作符”。因此,我认为答案是,截至 .NET 3.5,并不支持该功能。
7. 单子空值检查
移除了在访问属性或方法之前检查null的需要。在Groovy中称为Safe Navigation Operator。
之前的写法
if (points != null) {
var next = points.FirstOrDefault();
if (next != null && next.X != null) return next.X;
}
return -1;
之后
var bestValue = points?.FirstOrDefault()?.X ?? -1;
我曾试图使用一个我写的结构体来完成这个任务,它与Nullable<T>
非常相似。使用Nullable<T>
,你可以做如下操作:
Nullable<Guid> id1 = null;
Guid id2 = id1 ?? Guid.NewGuid();
它在将id1
从Nullable<Guid>
隐式转换为Guid
时没有问题,尽管Nullable<T>
仅定义了一个显式
转换到类型T
。但是,对于我的自定义类型,使用相同的方法会出现错误:
运算符'??'不能应用于类型为'MyType'和'Guid'的操作数
因此,我认为编译器内置了一些魔法,为Nullable<T>
做了特殊处理。作为替代方案...
我们无法重写??
运算符,但如果您想让合并运算符评估底层值而不是类(或结构体,在我的情况下),您只需使用一个方法即可,这样需要非常少的额外按键。对于上面的例子,代码如下:
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
本身实际上不能为null。对于一个类,只要你要检查的值被公开,扩展方法就可以处理实例是否为空:
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";
return instance.MyValue != null ? instance : new MyClass("Default");
instance
为null,这将抛出NullReferenceException。你需要将它修改为(instance != null && instance.MyValue != null) ? instance : new MyClass("Default");
。 - Bobson