【问题标题】:It is possible to overload `??` operator in C#?在 C# 中是否可以重载 `??` 运算符?
【发布时间】:2012-09-04 03:16:15
【问题描述】:

我读过这篇MSDN document 关于运算符重载的文章。

在该示例中,使用的运算符为+-,还可以定义其他运算符*/

我想重载?? 运算符以用于类似字符串

string emptyString = emptyString ?? "OtherValue";

而不是

string emptyString = string.IsNullOrEmpty(emptyString) ? "OtherValue" : emptyString;

不想将字符串转换为对象并使用??进行比较。

我知道?? 用于可空值类型,如 MSDN 所说:

??运算符称为空合并运算符,用于为可空值类型或引用类型定义默认值。

如果操作数不为空,则返回左侧操作数;否则返回正确的操作数。

我想问你是否可以在 C# 中重载这个运算符。上面的例子是需要使用??的简单情况。

【问题讨论】:

    标签: c# operators null-coalescing-operator


    【解决方案1】:

    不,你不能。

    一个简单的解决方法是使用扩展方法:

     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'
    

    尽管请注意,我发现为了让扩展方法出现在一流的编译时常量(例如 "")上,您需要将该扩展方法合并到 System 中;即:

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

    但是,您有没有看到 - 您必须使用强制转换来启动转换,而且确实非常丑陋和可怕,好吧,不要这样做。但你可以不会。

    我还需要更多免责声明吗?

    关于显式转换的一点说明

    我的很大一部分人认为string result = fs ?? foo; 应该可以工作,但事实并非如此。原因是?? 执行的null 检查仅在左侧的引用上——它与类型无关,除非是可空值类型。反编译 IL,引用被简单地加载到堆栈上,然后检查它是否评估为真或假,代码在该点分支到将值加载到堆栈的两个进一步操作之一(这是 @然后调用 987654333@ 运算符)。对于可为空的值类型,这种行为是不同的——编译器知道这些,因此会相应地改变它的行为。

    【讨论】:

    • 我还想为字符串扩展。
    • 也许应该用return string.IsNullOrEmpty(instance) ? alt : string; 代替return string.IsNullOrEmpty(instance) ? alt : instance;
    • 是的 - 哎呀!昨晚听网球的我睡得很晚——睡 4 小时做一个 SO 答案不是很好
    【解决方案2】:

    根据this 你不能超载??运算符。

    【讨论】:

      【解决方案3】:

      没有。请看这里Overloadable Operators C#。 Section '这些操作符不能被重载。'

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-02-22
        • 2015-01-01
        • 2010-10-20
        • 2010-10-21
        • 2017-02-05
        • 2012-01-12
        • 2017-05-06
        相关资源
        最近更新 更多