我正在尝试使用扩展方法向C# StringBuilder 类添加一个operater重载。具体来说,给定 StringBuilder sb ,我希望 sb + =" text" 等同于 sb.Append(" ;文本&QUOT。)

以下是为 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

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

有帮助吗?

解决方案

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

Mads Torgersen,C#语言PM说:

  

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

     

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

编辑:

我刚注意到,Mads在同一篇文章:

  

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

     

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


此功能目前已在桌面上(可能)用于C#8.0。 Mads会谈关于实施它的更多信息此处

其他提示

如果你控制你想要使用的地方,那么“扩展运算符” (无论如何你通常使用扩展方法),你可以这样做:

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 声明所需的 + 运算符。这样, StringBuilder 就可以传递给 ReceiveImportantMessage ,它将被静默转换为 StringBuilderWrapper ,其中 + 可以使用>运算符。

为了使这个事实对调用者更加透明,你可以将 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 更容易理解。

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

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

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

虽然不可能做操作符,但你总是可以创建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;    
        }
    }


}

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

在这里阅读答案(并且看到答案是“不”)后,为了满足我的特殊需求,我选择了一个结合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);

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

可以使用包装器和扩展来对其进行操作,但无法正确执行。你以垃圾结束,这完全违背了目的。 我在这里的某个地方有一个帖子可以做到,但它毫无价值。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top