Pergunta

Eu estou tentando usar métodos de extensão para adicionar uma sobrecarga operater para a classe C # StringBuilder. Especificamente, dado StringBuilder sb, eu gostaria sb += "text" para se tornar equivalente a sb.Append("text").

Aqui está a sintaxe para criar um método de extensão para StringBuilder:

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

Ele adiciona com sucesso o método de extensão blah ao StringBuilder.

Infelizmente, sobrecarga de operadores não parece trabalho:

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

Entre outras questões, a palavra-chave this não é permitido neste contexto.

está adicionando sobrecargas de operador via métodos de extensão possível? Se sim, qual é a maneira correta de fazê-lo?

Foi útil?

Solução

Isto não é possível no momento, porque os métodos de extensão devem estar em classes estáticas e classes estáticas não podem ter sobrecargas de operador.

Mads Torgersen, Linguagem C # PM diz:

... para as Orcas liberar decidimos tomar a abordagem cautelosa e adicionar apenas métodos de extensão regulares, como oposição a propriedades de Extensão, eventos, operadores, métodos estáticos, etc etc. métodos de extensão foram regulares o que precisávamos para LINQ, e eles tiveram um design sintaticamente mínimo que não poderia ser facilmente imitado por algum dos outros tipos de membros.

Estamos cada vez mais conscientes que outros tipos de elementos de extensão poderia ser útil, e por isso vamos voltar a esta questão depois de Orcas. Não garantias, embora!

Editar:

Eu notei, Mads escreveu mais no mesmo artigo :

Lamento relatório que não vamos estar fazendo isso na próxima versão. Nós que os membros de extensão take muito seriamente em nossos planos, e passou um muito esforço tentando levá-los certo, mas, no final, não conseguia -a suave o suficiente, e decidiu dar maneira de outras características interessantes.

Este ainda está em nosso radar para o futuro lançamentos. O que vai ajudar é se conseguirmos uma boa quantidade de cenários convincentes que pode ajudar a conduzir o projeto direito.


Este recurso está sobre a mesa (potencialmente) para C # 8.0. Mads conversações um pouco mais sobre a sua aplicação aqui .

Outras dicas

Se você controlar os lugares onde você deseja usar este "operador de extensão" (que faz normalmente com métodos de extensão de qualquer maneira), você pode fazer algo como isto:

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

} 

A classe StringBuilderWrapper declara um conversão implícita operador de uma StringBuilder < em> e declara o operador + desejado. Desta forma, um StringBuilder pode ser passado para ReceiveImportantMessage, que vai ser convertido em silêncio para um StringBuilderWrapper, onde o operador + pode ser utilizado.

Para fazer este fato mais transparente para os chamadores, você pode declarar ReceiveImportantMessage como tomar um StringBuilder e utilize o código como este:

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

Ou, para usá-lo em linha onde você já está usando um StringBuilder, você pode simplesmente fazer isso:

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

Eu criei um post sobre como usar uma abordagem semelhante à make IComparable mais compreensível.

Parece que este momento não é possível - há um problema de feedback aberta solicitando esse mesmo recurso no Microsoft Connect:

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

sugerindo que poderia aparecer em uma versão futura, mas não é implementado para a versão atual.

Embora não seja possível fazer os operadores, você poderia sempre apenas criar Add (ou Concat), subtrair, e comparar métodos ....

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! Eu estava olhando para cima "operador de extensão sobrecarga" com exatamente o mesmo desejo, para sb + = (coisa).

Depois de ler as respostas aqui (e vendo que a resposta é "não"), para as minhas necessidades particulares, fui com um método de extensão que combina sb.AppendLine e sb.AppendFormat, e aparência mais arrumada do que qualquer um.

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

}

E assim,

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

Não é uma resposta geral, mas pode ser de interesse para os futuros candidatos a ver este tipo de coisa.

Sua possível Rigg-lo com um invólucro e extensões, mas impossível de fazê-lo corretamente. Você acaba com o lixo que derrota totalmente o efeito. Eu tenho um post em algum lugar por aqui que faz isso, mas o seu valor.

Btw Todas as conversões numéricas criar lixo no construtor string que precisa ser corrigido. Eu tive que escrever um wrapper para o que não funciona e eu usá-lo. Que vale a pena perusing.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top