C#拡張メソッドを使用した演算子のオーバーロード
-
05-07-2019 - |
質問
拡張メソッドを使用して、演算子のオーバーロードをC# StringBuilder
クラスに追加しようとしています。具体的には、 StringBuilder
sb
を指定すると、 sb + =" text"
が sb.Append(&quotと同等になります; 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
はこのコンテキストでは許可されていません。
拡張メソッドを介して演算子のオーバーロードを追加できますか?もしそうなら、それを行う適切な方法は何ですか?
解決
拡張メソッドは静的クラスに存在する必要があり、静的クラスには演算子オーバーロードを含めることができないため、これは現在不可能です。
Mads Torgersen、C#言語PMは次のように述べています:
... Orcasのリリースでは、 慎重なアプローチを取り、追加します 通常の拡張メソッドのみ。 拡張プロパティとは対照的に、 イベント、演算子、静的メソッドなど など。通常の拡張方法は LINQに必要なもの、そして彼らは 構文的に最小限の設計 簡単に真似できない人もいた 他の種類のメンバー。
私たちはますます気づいています 他の種類の拡張メンバー 役に立つかもしれないので、戻ります Orcasの後のこの問題に。いや しかし、保証!
編集:
気がついたのですが、Madsは同じ記事:
私たちはしないと報告して申し訳ありません 次のリリースでこれを行うこと。我々 エクステンションのメンバーをとても連れて行った 私たちの計画で真剣に、そして過ごした それらを取得しようとして多くの努力 正しいが、最終的には取得できませんでした それは十分に滑らかで、与えることを決めた 他の興味深い機能への道。
これはまだ将来のレーダーです リリース。助けになるのは かなりの量の説得力のあるシナリオ 適切な設計を推進するのに役立ちます。
この機能は現在、C#8.0の(潜在的に)テーブルにあります。 Mads talks実装についてもう少しこちら。
他のヒント
この「拡張演算子」を使用する場所を制御する場合(とにかく拡張メソッドで通常行う)、次のようなことができます:
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
クラスは、暗黙的な変換演算子を宣言します StringBuilder
and から、目的の +
演算子を宣言します。このようにして、 StringBuilder
を 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
をより理解しやすくします。
これは現在可能ではないようです-Microsoft Connectでこの機能を要求するオープンフィードバックの問題があります:
http://connect.microsoft.com/VisualStudio/feedback/ ViewFeedback.aspx?FeedbackID = 168224
将来のリリースで登場する可能性があるが、現在のバージョンでは実装されていないことを示唆しています。
演算子を実行することはできませんが、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;
}
}
}
はい! 「拡張演算子のオーバーロード」を探していました。 sb + =(thing)の場合、まったく同じ欲求で。
ここで答えを読んだ(そして答えが「いいえ」であることがわかった)後、私の特定のニーズに合わせて、sb.AppendLineとsb.AppendFormatを組み合わせた拡張メソッドを使用しました。 p>
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);
}
}
そして、
sb.Line("the first thing is {0}",first);
sb.Line("the second thing is {0}", second);
一般的な答えではありませんが、この種のことを検討している将来の探求者にとって興味があるかもしれません。
ラッパーと拡張機能でリギングすることは可能ですが、適切に行うことはできません。目的を完全に無効にするゴミで終わります。 私はここでそれを行う投稿をどこかに持っていますが、それは価値がありません。
ところで すべての数値変換は、修正が必要な文字列ビルダーでガベージを作成します。動作するラッパーを作成する必要があり、それを使用します。それは熟読する価値がある。