运算符使用C#扩展方法重载

时间:2008-10-05 20:59:04

标签: c# extension-methods operator-overloading

我正在尝试使用扩展方法向C#StringBuilder类添加一个operater重载。具体而言,鉴于StringBuilder sb,我希望sb += "text"等同于sb.Append("text")

以下是为StringBuilder创建扩展方法的语法:

public static class sbExtensions
{
    public static StringBuilder blah(this StringBuilder sb)
    {
        return sb;
    }
} 

它成功地将blah扩展方法添加到StringBuilder

不幸的是,运算符重载似乎不起作用:

public static class sbExtensions
{
    public static StringBuilder operator +(this StringBuilder sb, string s)
    {
        return sb.Append(s);
    }
} 

除其他问题外,在此上下文中不允许使用关键字this

是否可以通过扩展方法添加运算符重载?如果是这样,那么正确的方法是什么?

6 个答案:

答案 0 :(得分:144)

目前这不可能,因为扩展方法必须在静态类中,而静态类不能有操作符重载。

Mads Torgersen,C#语言PM说:

  

...对于Orcas的发布,我们决定   采取谨慎的方法并添加   只有常规的扩展方法,如   反对延伸财产,   事件,运算符,静态方法等   等常规扩展方法   我们需要LINQ,他们有   一种语法上最小的设计   一些人不可能轻易模仿   其他成员的种类。

     

我们越来越意识到了   其他类型的扩展成员   可能有用,所以我们会回来   在Orcas之后的这个问题。没有   但保证!

编辑:

我刚注意到,Mads在same article中写了更多内容:

  

我很遗憾地报告说我们不会   在下一个版本中这样做。我们   确实非常接受扩展会员   认真地在我们的计划中,花了一个   我们付出了很多努力   对,但最终我们无法得到   它足够顺利,并决定给予   其他有趣的功能。

     

这仍然是我们未来的关注点   版本。如果我们得到了什么会有所帮助   大量引人注目的场景   这有助于推动正确的设计。


This feature is currently on the table (potentially) for C# 8.0. Mads更多地谈论实施它​​here

答案 1 :(得分:54)

如果你控制你想要使用这个“扩展操作符”的地方(你通常使用扩展方法),你可以这样做:

class Program {

  static void Main(string[] args) {
    StringBuilder sb = new StringBuilder();
    ReceiveImportantMessage(sb);
    Console.WriteLine(sb.ToString());
  }

  // the important thing is to use StringBuilderWrapper!
  private static void ReceiveImportantMessage(StringBuilderWrapper sb) {
    sb += "Hello World!";
  }

}

public class StringBuilderWrapper {

  public StringBuilderWrapper(StringBuilder sb) { StringBuilder = sb; }
  public StringBuilder StringBuilder { get; private set; }

  public static implicit operator StringBuilderWrapper(StringBuilder sb) {
    return new StringBuilderWrapper(sb);
  }

  public static StringBuilderWrapper operator +(StringBuilderWrapper sbw, string s) { 
      sbw.StringBuilder.Append(s);
      return sbw;
  }

} 

StringBuilderWrapper类声明来自StringBuilder implicit conversion operator声明所需的+运算符。这样,StringBuilder就可以传递给ReceiveImportantMessageStringBuilderWrapper会以静默方式转换为+,可以使用ReceiveImportantMessage运算符。

为了使这一事实对来电者更加透明,您可以将StringBuilder声明为 private static void ReceiveImportantMessage(StringBuilder sb) { StringBuilderWrapper sbw = sb; sbw += "Hello World!"; } 并使用以下代码:

StringBuilder

或者,要在内联使用 StringBuilder sb = new StringBuilder(); StringBuilderWrapper sbw = sb; sbw += "Hello World!"; Console.WriteLine(sb.ToString()); 的情况下使用它,您可以直接执行此操作:

IComparable

我创建a post关于使用类似的方法使{{1}}更容易理解。

答案 2 :(得分:8)

目前看来这是不可能的 - 在Microsoft Connect上有一个开放的反馈问题请求这个功能:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=168224

建议它可能出现在将来的版本中,但不会针对当前版本实现。

答案 3 :(得分:1)

虽然不可能做操作符,但你总是可以创建Add(或Concat),Subtract和Compare方法....

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;    

namespace Whatever.Test
{
    public static class Extensions
    {
        public static int Compare(this MyObject t1, MyObject t2)
        {
            if(t1.SomeValueField < t2.SomeValueField )
                return -1;
            else if (t1.SomeValueField > t2.SomeValueField )
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }

        public static MyObject Add(this MyObject t1, MyObject t2)
        {
            var newObject = new MyObject();
            //do something  
            return newObject;

        }

        public static MyObject Subtract(this MyObject t1, MyObject t2)
        {
            var newObject= new MyObject();
            //do something
            return newObject;    
        }
    }


}

答案 4 :(得分:0)

哈!我正在查找&#34;扩展运算符重载&#34; sb + =(thing)。具有完全相同的愿望。

在这里阅读答案(并且看到答案是&#34;没有&#34;),为了我的特殊需要,我选择了一个结合了sb.AppendLine和sb.AppendFormat的扩展方法,看起来比任

public static class SomeExtensions
{
    public static void Line(this StringBuilder sb, string format, params object[] args)
    {
        string s = String.Format(format + "\n", args);
        sb.Append(s);
    }

}

所以,

sb.Line("the first thing is {0}",first);
sb.Line("the second thing is {0}", second);

不是一般性答案,但未来寻求此类事情的求职者可能会感兴趣。

答案 5 :(得分:0)

可以使用包装器和扩展来绑定它,但不能正确地完成它。你以垃圾结束,这完全违背了目的。 我在这里的某个地方有一个帖子可以做到,但它毫无价值。

顺便说一下 所有数字转换都在字符串构建器中创建需要修复的垃圾。我必须编写一个包装器,它可以工作并使用它。这值得细读。