184

StringBuilder拡張メソッドを使用して、演算子のオーバーロードを C#クラスに追加しようとしています。具体的には、与えられたに対して、と同等になり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はこのコンテキストでは許可されていません。

拡張メソッドを介して演算子のオーバーロードを追加できますか? もしそうなら、それについて行く適切な方法は何ですか?

4

6 に答える 6

158

拡張メソッドは静的クラスにある必要があり、静的クラスは演算子のオーバーロードを持つことができないため、これは現在不可能です。ただし、この機能は、C# の将来のリリースで検討されてます。Mads は、 2017 年のこのビデオで、それを実装することについてもう少し話しました。

現在実装されていない理由について、C# 言語 PM の Mads Torgersen 氏は次のように述べています。

...Orcas リリースでは、拡張プロパティ、イベント、演算子、静的メソッドなどとは対照的に、慎重なアプローチを取り、通常の拡張メソッドのみを追加することにしました。通常の拡張メソッドは LINQ に必要なものでした。他のメンバーの種類の一部では簡単に模倣できない、構文的に最小限の設計。

他の種類の拡張メンバーが役立つ可能性があることをますます認識しているため、Orcas の後でこの問題に戻ります。ただし、保証はありません!

同じ記事のさらに下:

申し訳ありませんが、次のリリースではこれを行わない予定です。私たちは計画の中で拡張メンバーを非常に真剣に受け止め、それらを正しくするために多くの努力を費やしましたが、最終的に十分にスムーズに進めることができず、他の興味深い機能に道を譲ることにしました.

これは、今後のリリースに向けてまだ検討中です。適切な設計を推進するのに役立つ説得力のあるシナリオを大量に入手できれば、助けになるでしょう。

于 2008-10-05T21:04:11.473 に答える
61

この「拡張演算子」を使用する場所を制御する場合 (通常は拡張メソッドで行います)、次のようなことができます。

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クラスは、 a からの暗黙の変換演算子StringBuilder 宣言し、目的の+演算子を宣言します。このようにして、 aStringBuilderを に渡すことができますReceiveImportantMessage。これは、暗黙のうちに に変換されStringBuilderWrapper、そこで+演算子を使用できます。

この事実を呼び出し元に対してより透過的にするために、次のようなコードを使用するReceiveImportantMessageことを宣言できます。StringBuilder

  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

于 2010-02-03T19:08:09.693 に答える
8

これは現在不可能なようです - Microsoft Connect でまさにこの機能を要求する未解決のフィードバックの問題があります。

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

将来のリリースで表示される可能性があることを示唆していますが、現在のバージョンでは実装されていません。

于 2008-10-05T21:05:59.160 に答える
1

演算子を実行することはできませんが、いつでも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;    
        }
    }


}
于 2012-05-17T21:18:32.930 に答える