Question

J'essaie d'utiliser des méthodes d'extension pour ajouter une surcharge d'opérateur à la classe C # StringBuilder . Plus précisément, étant donné que StringBuilder sb , je voudrais que sb + = "texte" soit devienne équivalent à sb.Append (" ; texte ") .

Voici la syntaxe pour créer une méthode d'extension pour StringBuilder :

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

Il ajoute avec succès la méthode d'extension blah au StringBuilder .

Malheureusement, la surcharge de l'opérateur ne semble pas fonctionner:

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

Parmi les autres problèmes, le mot clé this n'est pas autorisé dans ce contexte.

L’ajout de surcharges d’opérateurs via des méthodes d’extension est-il possible? Si oui, quelle est la bonne façon de s'y prendre?

Était-ce utile?

La solution

Ceci n'est actuellement pas possible, car les méthodes d'extension doivent être dans des classes statiques et les classes statiques ne peuvent pas avoir de surcharge d'opérateur.

Mads Torgersen, c # langage PM déclare:

  

... pour la version Orcas, nous avons décidé de   adopter une approche prudente et ajouter   seulement des méthodes d'extension régulières, comme   opposé aux propriétés d'extension,   événements, opérateurs, méthodes statiques, etc.   etc. Les méthodes d’extension habituelles étaient   ce dont nous avions besoin pour LINQ, et ils avaient   une conception syntaxiquement minimale   ne pouvait pas être facilement imité pour certains   des autres types de membres.

     

Nous prenons de plus en plus conscience   que d'autres types de membres d'extension   pourrait être utile, et donc nous reviendrons   à cette question après Orcas. Non   des garanties, cependant!

Modifier:

Je viens de remarquer que Mads a écrit davantage dans le même article :

  

Je suis désolé d'annoncer que nous ne le ferons pas   faire cela dans la prochaine version. nous   a pris très membres de l'extension   sérieusement dans nos plans, et passé une   beaucoup d'efforts essayant de les obtenir   droit, mais à la fin nous ne pouvions pas obtenir   assez lisse, et a décidé de donner   chemin vers d'autres fonctionnalités intéressantes.

     

Ceci est toujours sur notre radar pour l'avenir   communiqués. Ce qui aidera, c'est si nous obtenons   une bonne quantité de scénarios convaincants   cela peut aider à conduire le bon design.

Cette fonctionnalité est actuellement sur la table (potentiellement) pour le C # 8.0. Entretiens avec Mads un peu plus sur sa mise en œuvre ici .

Autres conseils

Si vous contrôlez les endroits où vous souhaitez utiliser cet " poste opérateur " (ce que vous faites normalement avec les méthodes d’extension de toute façon), vous pouvez faire quelque chose comme ceci:

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

} 

La classe StringBuilderWrapper déclare un opérateur de conversion implicite depuis un StringBuilder et déclare l'opérateur + souhaité. De cette façon, un StringBuilder peut être passé à ReceiveImportantMessage , qui sera converti silencieusement en un StringBuilderWrapper , où + opérateur peut être utilisé.

Pour rendre ce fait plus transparent pour les appelants, vous pouvez déclarer ReceiveImportantMessage comme prenant un StringBuilder et utiliser simplement le code suivant:

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

Ou, pour l'utiliser en ligne là où vous utilisez déjà un StringBuilder , vous pouvez simplement faire ceci:

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

J'ai créé un publication sur l'utilisation d'une approche similaire pour rendre IComparable plus compréhensible.

Il semble que cela ne soit pas possible actuellement. Un problème de retour d'information demandant cette fonctionnalité sur Microsoft Connect a été ouvert:

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

suggère qu'il apparaisse dans une version ultérieure, mais qu'il ne soit pas implémenté pour la version actuelle.

Même s’il n’est pas possible de faire les opérateurs, vous pouvez toujours créer des méthodes Add (ou Concat), Subtract, et 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;    
        }
    }


}

Hah! Je cherchais & surcharge; surcharge de l'opérateur avec exactement le même désir, pour SB + = (chose).

Après avoir lu les réponses ici (et vu que la réponse est "non"), pour mes besoins particuliers, j’ai opté pour une méthode d’extension combinant sb.AppendLine et sb.AppendFormat, et qui a l’air plus soignée que les autres.

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

}

Et oui,

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

Ce n’est pas une réponse générale, mais cela pourrait intéresser les futurs chercheurs qui se tournent vers ce genre de choses.

Il est possible de le gréer avec un wrapper et des extensions mais impossible de le faire correctement. Vous vous retrouvez avec des ordures qui vont totalement à l'encontre du but recherché. J'ai un message quelque part ici qui le fait, mais c'est nul.

Btw Toutes les conversions numériques créent des déchets dans le générateur de chaînes qui doivent être corrigés. J'ai dû écrire un emballage pour ce qui fonctionne et je l'utilise. Cela vaut la peine de le lire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top