Frage

Ich versuche, Erweiterungsmethoden zu verwenden, um eine operater Überlastung der C # StringBuilder Klasse hinzuzufügen. Insbesondere gegeben StringBuilder sb, würde ich sb += "text" gerne sb.Append("text") äquivalent werden.

Hier ist die Syntax für eine Erweiterungsmethode für StringBuilder erstellen:

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

Es fügt erfolgreich die blah Erweiterungsmethode zum StringBuilder.

Leider Betreiber Überlastung scheint nicht zu funktionieren:

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

Unter anderem das Schlüsselwort this ist in diesem Zusammenhang nicht erlaubt.

Hinzufügen Betreiber Überlastungen über Erweiterungsmethoden möglich? Wenn ja, was ist der richtige Weg, um darüber zu gehen?

War es hilfreich?

Lösung

Dies ist derzeit nicht möglich, da Erweiterungsmethoden in statischen Klassen sein müssen und statische Klassen können nicht überladene Operatoren haben.

Mads Torgersen, C # Sprache PM sagt:

  

... für die Orcas Release haben wir beschlossen,   nehmen Sie die vorsichtigen Ansatz und fügen   nur regelmäßige Erweiterungsmethoden, wie   Gegensatz zu extention Eigenschaften,   Ereignisse, Operatoren, statische Methoden, etc   Die regulären Erweiterungsmethoden waren   was wir brauchten für LINQ, und sie hatten   ein syntaktisch minimalistisches Design, dass   nicht leicht für einige nachgeahmt werden könnte   die anderen Mitglied Arten.

     

Wir werden immer bewusst   dass andere Arten von Erweiterungselementen   könnte nützlich sein, und so werden wir zurückkehren   zu diesem Thema nach Orcas. Nein   Garantien, aber!

Edit:

Ich habe gerade bemerkt, Mads schrieb mehr in der gleichen Artikel :

  

Es tut mir leid zu berichten, dass wir nicht   dies in der nächsten Version tun. Wir   dauerte sehr Verlängerungselemente   ernsthaft in unseren Plänen, und verbrachte eine   viel Mühe versuchen, sie zu bekommen   Recht, aber am Ende konnten wir nicht bekommen   sie glatt genug, und beschlossen, geben   Art und Weise zu anderen interessanten Funktionen.

     

Dies ist immer noch auf unserem Radar für Zukunft   Mitteilungen. Was hilft, wenn wir bekommen   eine gute Menge von überzeugenden Szenarien   das kann das richtige Design helfen fahren.


Diese Funktion ist derzeit auf dem Tisch (potentiell) für C # 8.0. Mads Gespräche ein bisschen mehr darüber hier .

Andere Tipps

Wenn Sie die Orte steuern, wo Sie den „-Erweiterung Operator“ verwendet werden sollen (die Sie normalerweise mit Erweiterungsmethoden tun sowieso), können Sie etwas tun:

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

} 

Die StringBuilderWrapper Klasse deklariert eine von einem StringBuilder rel="noreferrer"> < em> und erklärt den gewünschten + Operator. Auf diese Weise kann ein StringBuilder ReceiveImportantMessage übergeben werden, die leise zu einem StringBuilderWrapper umgewandelt werden, in dem der + Operator verwendet werden kann.

Um diese Tatsache transparenter Anrufer zu machen, können Sie ReceiveImportantMessage als Einnahme eine StringBuilder erklären und verwenden nur Code wie folgt:

  private static void ReceiveImportantMessage(StringBuilder sb) {
    StringBuilderWrapper sbw = sb;
    sbw += "Hello World!";
  }

Oder, um es zu benutzen inline, wo Sie bereits ein StringBuilder verwenden, können Sie einfach tun:

 StringBuilder sb = new StringBuilder();
 StringBuilderWrapper sbw = sb;
 sbw += "Hello World!";
 Console.WriteLine(sb.ToString());

Ich habe ein Post über einen ähnlichen Ansatz zu machen IComparable verständlich.

Es scheint, dies ist derzeit nicht möglich - es ist ein offenes Feedback Problem diese sehr Funktion auf Microsoft Connect anfordernden:

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

was darauf hindeutet, es in einer zukünftigen Version erscheinen könnte, ist aber für die aktuelle Version nicht implementiert.

Auch wenn es nicht möglich ist, die Betreiber zu tun, könnte man immer hinzufügen nur erstellen (oder Concat), subtrahieren und Methoden vergleichen ....

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


}

Hah! Ich war auf der Suche nach oben „-Erweiterung Betreiber Überlastung“ mit genau dem gleichen Wunsch, für sb + = (Sache).

Nach dem die Antworten lesen Sie hier (und zu sehen, dass die Antwort „nein“), für meine besonderen Bedürfnisse, ging ich mit einem Verlängerungsverfahren, das sb.AppendLine und sb.AppendFormat kombiniert und sieht aufgeräumter als beide.

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

}

Und so,

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

Nicht eine allgemeine Antwort, aber zukünftige Suchende von Interesse sein können auf diese Art der Sache suchen.

Es ist möglich, Rigg mit einem Wrapper und Erweiterungen aber unmöglich, es richtig zu machen. Sie enden mit Müll, die völlig den Zweck besiegt. Ich habe einen Post irgendwo hier, das tut es, aber es ist wertlos.

Btw Alle numerischen Konvertierungen erstellen Müll in String-Builder, die behoben werden muss. Ich hatte einen Wrapper für das schreiben, die Arbeit erledigt und ich verwende es. Das lohnt sich durchlesen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top