Перегрузка оператора с помощью методов расширения C #

Я пытаюсь использовать методы расширения для добавления перегрузки оператором в class 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 не разрешено в этом контексте.

Возможны ли дополнительные перегрузки оператора с помощью методов расширения? Если да, то каков правильный способ этого?

    В настоящее время это невозможно, поскольку методы расширения должны быть в статических classах, а статические classы не могут иметь перегрузки операторов.

    Mads Torgersen, C # Language PM говорит:

    … для выпуска Orcas мы решили принять осторожный подход и добавить только обычные методы расширения, в отличие от свойств расширения, событий, операторов, статических методов и т. д. и т. д. Регулярные методы расширения были тем, что нам нужно для LINQ, и они синтаксически минимальный дизайн, который нельзя было легко перенести на некоторые из других типов участников.

    Мы все больше осознаем, что другие виды членов расширения могут быть полезны, и поэтому мы вернемся к этому вопросу после Orcas. Однако никаких гарантий!

    Редактировать:

    Я только что заметил, Мэдс написал больше в той же статье :

    Мне жаль сообщить, что мы не будем делать этого в следующем выпуске. Мы очень серьезно относились к продлению членства в наших планах и прилагали немало усилий, пытаясь их исправить, но в итоге мы не смогли получить его достаточно гладко и решили уступить другим интересным функциям.

    Это все еще в нашем радаре для будущих выпусков. Что поможет, если мы получим достаточно много убедительных сценариев, которые могут помочь управлять правильным дизайном.


    Эта функция в настоящее время находится в таблице (потенциально) для C # 8.0. Мэдс говорит немного больше о его реализации здесь .

    Если вы контролируете места, где вы хотите использовать этот «оператор расширения» (который вы обычно используете с методами расширения), вы можете сделать что-то вроде этого:

     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 , который будет ReceiveImportantMessage преобразован в StringBuilderWrapper , где может использоваться оператор + .

    Чтобы сделать этот факт более прозрачным для вызывающих, вы можете объявить ReceiveImportantMessage как взятие ReceiveImportantMessage и просто использовать такой код:

      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 + = (вещь).

    Прочитав ответы здесь (и увидев, что ответ «нет»), для моих конкретных потребностей я пошел с расширением, который объединяет 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); 

    Не общий ответ, но может быть интересен будущим искателям, рассматривающим такие вещи.

    Его можно установить с помощью обертки и расширений, но сделать это невозможно. Вы заканчиваете мусором, который полностью побеждает цель. У меня есть почта где-то здесь, что делает это, но это бесполезно.

    Btw Все числовые преобразования создают мусор в построителе строк, который необходимо исправлять. Мне пришлось написать оболочку для того, что работает, и я использую ее. Это заслуживает внимания.

    Давайте будем гением компьютера.