可以在C#中重载“??”运算符?
我读到这篇关于操作符重载的文章 在该示例中,使用的运算符是可以在C#中重载“??”运算符?,c#,operators,null-coalescing-operator,C#,Operators,Null Coalescing Operator,我读到这篇关于操作符重载的文章 在该示例中,使用的运算符是+,-,还可以定义其他的*或/ 我想重载??运算符以用于字符串,如 string emptyString = emptyString ?? "OtherValue"; 而不是 string emptyString = string.IsNullOrEmpty(emptyString) ? "OtherValue" : emptyString; 我不想将字符串转换为对象并使用?进行比较 我知道??用于可空值类型,MSDN是这么说的: 这
+
,-
,还可以定义其他的*
或/
我想重载??
运算符以用于字符串,如
string emptyString = emptyString ?? "OtherValue";
而不是
string emptyString = string.IsNullOrEmpty(emptyString) ? "OtherValue" : emptyString;
我不想将字符串转换为对象并使用?
进行比较
我知道??
用于可空值类型,MSDN是这么说的:
这个??运算符称为空合并运算符,用于为可空值类型或引用类型定义默认值
如果操作数不为空,则返回左侧操作数;否则返回正确的操作数
我想问您是否有可能在C#中重载此运算符。上面的例子是一个简单的情况,需要使用
??否。请看这里。“不能重载这些运算符”部分。否。请查看此处。“不能重载这些运算符”部分。根据您的说明,不能重载??操作员。根据您不能超载??接线员。不,你不能
一个简单的解决方法是使用扩展方法:
public static string IfNullOrEmpty(this string instance, string alt){
return string.IsNullOrEmpty(instance) ? alt : instance;
}
var str1 = "".IfNullOrEmpty("foo"); //'foo'
var str2 = ((string)null).IfNullOrEmpty("bar"); //'bar'
var str3 = "Not null or empty".IfNullOrEmpty("not used"); //'not null or empty'
尽管注意,我发现为了使扩展方法出现在第一类编译时常量上,例如”
,您需要将该扩展方法合并到系统中;i、 e:
namespace System {
public static class MyStringExtensions {
// method here
}
}
不要这样做-只是为了好玩
您可以(尽管我不建议这样做)为String
编写一个包装器类型,其中包含String
之间的隐式强制转换运算符,如果字符串为空,则返回null
,因此在该类型的实例上使用??
运算符将产生正确的行为:
public class FakeString
{
private string _source;
public FakeString(string source)
{
}
public static implicit operator string(FakeString instance)
{
return string.IsNullOrEmpty(instance._source) ? null : instance._source;
}
public static implicit operator FakeString(string source)
{
return new FakeString(source);
}
}
[TestMethod]
public void Test()
{
FakeString fs = "";
string result = (string)fs ?? "foo";
Assert.AreEqual("foo", result);
}
然而,你可以看到-你必须使用铸造开始转换,真的是非常丑陋和可怕的,好吧,只是不要这样做。但是你可以。我不会的
我需要更多的免责声明吗
关于该明确演员阵容的一点注意事项
我的很大一部分人认为stringresult=fs??傅代码>应该可以工作,但不能。原因是由??
执行的null
检查仅位于左侧的参考上-它的类型不可知,可空值类型除外。反编译IL时,只需将引用加载到堆栈上,然后检查其计算结果是否为true或false,代码在该点分支到将值加载到堆栈上的两个后续操作之一(这就是调用FakeString
操作符的地方)。对于可空值类型,这种行为不同-编译器知道这些,因此会相应地更改其行为。不,您不能
一个简单的解决方法是使用扩展方法:
public static string IfNullOrEmpty(this string instance, string alt){
return string.IsNullOrEmpty(instance) ? alt : instance;
}
var str1 = "".IfNullOrEmpty("foo"); //'foo'
var str2 = ((string)null).IfNullOrEmpty("bar"); //'bar'
var str3 = "Not null or empty".IfNullOrEmpty("not used"); //'not null or empty'
尽管注意,我发现为了使扩展方法出现在第一类编译时常量上,例如”
,您需要将该扩展方法合并到系统中;i、 e:
namespace System {
public static class MyStringExtensions {
// method here
}
}
不要这样做-只是为了好玩
您可以(尽管我不建议这样做)为String
编写一个包装器类型,其中包含String
之间的隐式强制转换运算符,如果字符串为空,则返回null
,因此在该类型的实例上使用??
运算符将产生正确的行为:
public class FakeString
{
private string _source;
public FakeString(string source)
{
}
public static implicit operator string(FakeString instance)
{
return string.IsNullOrEmpty(instance._source) ? null : instance._source;
}
public static implicit operator FakeString(string source)
{
return new FakeString(source);
}
}
[TestMethod]
public void Test()
{
FakeString fs = "";
string result = (string)fs ?? "foo";
Assert.AreEqual("foo", result);
}
然而,你可以看到-你必须使用铸造开始转换,真的是非常丑陋和可怕的,好吧,只是不要这样做。但是你可以。我不会的
我需要更多的免责声明吗
关于该明确演员阵容的一点注意事项
我的很大一部分人认为stringresult=fs??傅代码>应该可以工作,但不能。原因是由??
执行的null
检查仅位于左侧的参考上-它的类型不可知,可空值类型除外。反编译IL时,只需将引用加载到堆栈上,然后检查其计算结果是否为true或false,代码在该点分支到将值加载到堆栈上的两个后续操作之一(这就是调用FakeString
操作符的地方)。对于可空值类型,这种行为不同-编译器知道这些,因此会相应地更改其行为。我还考虑了字符串的扩展。可能不是返回字符串。IsNullOrEmpty(实例)?alt:字符串
应该是返回字符串。IsNullOrEmpty(实例)?alt:实例代码>是-哇!昨晚我很晚才起床听网球赛-greatI不认为在4小时睡眠时做一个SO答案也可以作为字符串的扩展。也许可以代替return string.IsNullOrEmpty(实例)?alt:字符串
应该是返回字符串。IsNullOrEmpty(实例)?alt:实例代码>是-哇!昨晚我听网球时睡得很晚——在4小时睡眠的情况下做这么一个答案并不好