用C#扩展方法重载操作符

我试图使用扩展方法将操作符重载添加到C# StringBuilder类。 具体来说,给定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在这种情况下是不允许的。

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


目前这是不可能的,因为扩展方法必须在静态类中,静态类不能有运算符重载。

Mads Torgersen,C#Language 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

这表明它可能出现在未来的版本中,但未在当前版本中实施。

链接地址: http://www.djcxy.com/p/73055.html

上一篇: Operator Overloading with C# Extension Methods

下一篇: what is the difference between overloading an operator inside or outside a class?