181 votes

Surcharge des opérateurs avec les méthodes d’Extension c#

Je suis d'essayer d'utiliser des méthodes d'extension pour ajouter un opérateur de surcharge pour le C# StringBuilder classe. Plus précisément, compte tenu de StringBuilder sb, j'aimerais sb += "text" de devenir l'équivalent d' sb.Append("text").

Voici la syntaxe pour la création d'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 l' blah méthode d'extension pour l' StringBuilder.

Malheureusement, la surcharge d'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 questions, le mot-clé this n'est pas autorisée dans ce contexte.

Ajoutez la surcharge de l'opérateur via des méthodes d'extension possible? Si oui, quelle est la bonne façon d'aller à ce sujet?

157voto

Jacob Krall Points 10327

Ce n'est pas possible à l'heure actuelle, parce que les méthodes d'extension doivent être dans les classes statiques, et les classes statiques ne peuvent pas avoir la surcharge de l'opérateur.

Mads Torgersen, Langage C# H dit:

...pour les Orques de presse, nous avons décidé de prendre l'approche prudente et ajouter seulement les méthodes d'extension, comme opposition à l'extension des propriétés, des événements, des opérateurs, des méthodes statiques, etc etc. Régulière des méthodes d'extension ont été ce qu'il nous fallait pour LINQ, et ils avaient d'un point de vue syntaxique minimale de la conception que ne pourrait pas être facilement imité pour certains de l'autre membre sortes.

Nous sommes de plus en plus conscients que d'autres types d'extension des membres pourrait être utile, donc nous reviendrons à cette question à la suite des Orques. Pas de garanties, si!

Edit:

Je viens de remarquer, Mads a écrit plus dans le même article:

Je suis désolée de vous dire que nous n'allons pas faire cela dans la prochaine version. Nous ne prenez extension des membres très sérieusement dans nos plans, et a passé une beaucoup d'efforts à essayer de les obtenir droit, mais à la fin nous ne pouvions pas obtenir il assez lisse, et a décidé de donner la voie à d'autres fonctionnalités intéressantes.

C'est encore sur notre radar pour l'avenir les rejets. Ce qui va aider est si nous obtenons une bonne quantité de scénarios intéressants qui peuvent contribuer à la bonne conception.

60voto

Jordão Points 29221

Si vous contrôlez les endroits où vous souhaitez utiliser cette "extension" d'opérateur (ce qui est normalement le faire avec des 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;
  }

} 

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

Pour faire de ce fait plus transparent pour les appelants, vous pouvez déclarer ReceiveImportantMessage que de prendre un StringBuilder et il suffit d'utiliser le code comme ceci:

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

Ou, pour utiliser inline 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 post sur l'utilisation d'une approche similaire pour faire IComparable plus compréhensible.

8voto

Dylan Beattie Points 23222

Il semble que ce n’est pas actuellement possible - il n’y a un problème de rétroaction ouverte demandant cette fonctionnalité très sur Microsoft Connect :

http://Connect.Microsoft.com/VisualStudio/Feedback/ViewFeedback.aspx?FeedbackID=168224

suggérant il peut apparaître dans une version ultérieure, mais n’est pas implémenté pour la version actuelle.

2voto

david van brink Points 2331

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

Après avoir lu les réponses ici (et voyant que la réponse est "non"), je suis allé avec une méthode d'extension qui combine sb.AppendLine et sb.AppendFormat, et qui semble plus ordonnée.

 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 donc,

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

Pas une réponse générale, mais peut intéresser les futurs chercheurs qui étudient ce genre de choses.

1voto

Chuck Rostance Points 1377

Bien qu'il ne soit pas possible de faire les opérateurs, vous pouvez toujours créer des méthodes Ajouter (ou Concat), Soustraire et Comparer ....

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


}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X