Überladen von Operatoren mit C # Erweiterungsmethoden
-
05-07-2019 - |
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?
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.