Pregunta

Estoy intentando usar métodos de extensión para agregar una sobrecarga de operador a la clase C # StringBuilder . Específicamente, dado StringBuilder sb , me gustaría que sb + = " texto " sea equivalente a sb.Append (" ; texto ") .

Aquí está la sintaxis para crear un método de extensión para StringBuilder :

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

Agrega con éxito el método de extensión blah al StringBuilder .

Lamentablemente, la sobrecarga del operador no parece funcionar:

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

Entre otras cuestiones, la palabra clave este no está permitida en este contexto.

¿Es posible agregar sobrecargas de operador a través de métodos de extensión? Si es así, ¿cuál es la forma correcta de hacerlo?

¿Fue útil?

Solución

Esto no es posible actualmente, porque los métodos de extensión deben estar en clases estáticas, y las clases estáticas no pueden tener sobrecargas de operadores.

Mads Torgersen, C # Language PM dice:

  

... para el lanzamiento de Orcas decidimos   tomar el enfoque cauteloso y añadir   Sólo métodos de extensión regulares, como   opuesto a las propiedades de extensión,   Eventos, operadores, métodos estáticos, etc.   Los métodos de extensión regulares eran   Lo que necesitábamos para LINQ, y tenían   un diseño sintácticamente minimalista que   No podría ser fácilmente imitado por algunos   de los otros tipos de miembros.

     

Cada vez somos más conscientes   que otros tipos de miembros de extensión   Podría ser útil, por lo que volveremos.   a este tema después de las orcas. No   Sin embargo, las garantías!

Editar:

Me di cuenta, Mads escribió más en el mismo artículo :

  

Lamento informar que no lo haremos   estaremos haciendo esto en el próximo lanzamiento. Nosotros   tomó miembros de la extensión muy   En serio en nuestros planes, y pasó una   mucho esfuerzo tratando de conseguirlos   bien, pero al final no pudimos conseguir   Lo suficientemente suave, y decidió dar   forma de otras características interesantes.

     

Esto todavía está en nuestro radar para el futuro   lanzamientos Lo que va a ayudar es si conseguimos   una buena cantidad de escenarios convincentes   Eso puede ayudar a impulsar el diseño correcto.


Esta función está actualmente en la tabla (potencialmente) para C # 8.0. Mads habla un poco más sobre su implementación here .

Otros consejos

Si controla los lugares donde desea utilizar esta " operador de extensión " (lo que normalmente haces con los métodos de extensión de todos modos), puedes hacer algo como esto:

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 clase StringBuilderWrapper declara una operador de conversión implícita de un StringBuilder y declara el operador deseado de + . De esta manera, un StringBuilder se puede pasar a ReceiveImportantMessage , que se convertirá silenciosamente en un StringBuilderWrapper , donde + Se puede utilizar el operador.

Para que este hecho sea más transparente para las personas que llaman, puede declarar que ReceiveImportantMessage toma un StringBuilder y solo usa el código como este:

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

O, para usarlo en línea donde ya estás usando un StringBuilder , simplemente puedes hacer esto:

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

Creé una publicación sobre el uso de un enfoque similar para haga que IComparable sea más comprensible.

Parece que esto no es posible actualmente. Hay un problema de comentarios abierto que solicita esta característica en Microsoft Connect:

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

sugiriendo que podría aparecer en una versión futura, pero no está implementado para la versión actual.

Aunque no es posible hacer los operadores, siempre puedes crear los métodos de Agregar (o Concat), Restar y Comparar ...

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! Estaba buscando "sobrecarga de operador de extensión" con exactamente el mismo deseo, para sb + = (cosa).

Después de leer las respuestas aquí (y viendo que la respuesta es " no "), para mis necesidades particulares, opté por un método de extensión que combina sb.AppendLine y sb.AppendFormat, y luce más ordenado que cualquiera.

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

}

Y así,

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

No es una respuesta general, pero puede ser de interés para futuros buscadores que miran este tipo de cosas.

Es posible manipularlo con una envoltura y extensiones, pero es imposible hacerlo correctamente. Se termina con la basura que derrota totalmente el propósito. Tengo un post en algún lugar aquí que lo hace, pero no tiene valor.

Por cierto Todas las conversiones numéricas crean basura en el generador de cadenas que necesita ser arreglado. Tuve que escribir un envoltorio para lo que funciona y lo uso. Eso vale la pena leerlo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top