SteringJoinerは、パフォーマンスの低下した文字列のスペルコードを救います.
http://www.cnblogs.com/coolcode/archive/2009/10/13/StringJoiner.html
前言
一般プログラマが持っている最も「強い」二つの武器はコピーと貼り付けです.
String
この文章は皆さんのテクニックを紹介したいです.
私たちは知っています.または、一日目にCハを勉強する時にstringのタイプを知っています.そして、一番簡単なつづり合わせのstringの書き方はすぐ分かります.
string s = string.Empty;
s += "Bruce";
s += "Who?";
s += "a guy think sth different...";
このような書き方は本当に簡単で素晴らしいです.C言語のstracat書き方に比べて、C書を使うのは本当に幸せです.またいつまでこのような書き方を支持するか分かりません.
s += "Bruce" + " Lee";
(いつから上記の書き方を支持するか分かりません.覚えています.Net 2.0はこのように書いてはいけません.Net 1.1は絶対だめです.必ず括弧を入れます.s += ("Bruce" + " Lee");
)StringBuider
しかし、この幸福感は初心者にはStringBuiderの存在を知らないかもしれません.たまに他の人の文章でStringBuiderを見ても、なぜ「+=」があるのか分かりません.
StringBuilder sb = new StringBuilder();
sb.Append("Bruce");
sb.Append("Who?");
sb.Append("a guy think sth different...");
信じられないかもしれませんが、企業で仕事をしているつもりです.Netで一年か二年働いている友達はまだStringBuiderの存在を知らない人がいます.特にAsp.Netの中では、多くの友達がCのプラカードを使ってフロントコードの山を作っています.Html文やJavaScript、さらにSQL文など、例外なく「+=」を使ってつづり合わせています.お尻をたたくと人が逃げてしまいます.何十行も残しています.
我々は、最初の方法を使って文字列をつなぎ合わせても、時間や空間の性能からしても、StringBuiderを使うよりは遠いことを知っているはずです.
いい子はここを見ると、早く帰って自分のあの「+=」を全部StringBuiderのアプリに変えてしまうかもしれません.とりあえず焦らないでください.方式から二転换するのはとても时间がかかります.绝対に苦しいです.今はどうやって一番速い方法で一つのコード性能を方式の二にアップするかを教えます.
Stering Joiner
簡単です.string sをString Joiner sに変えたら大成功です.すなわち
StringJoiner s = string.Empty;
s += "Bruce";
s += "Who?";
s += "a guy think sth different...";
なぜこんなに簡単に性能が上がるのですか?私をだましますか
もちろんみんなをだましているのではありませんて、マジックをするのではありませんて、文章の最後に性能のテストデータがあって、真相があります.
今は私にStringJoinerのベールを開けさせてください.最後にきっと言います.
StringJoinerは装飾者モードのようです.外にはStringBuiderが隠れています.魔術師が道具を一山袖に隠して観客を騙すのが好きです.
public class StringJoiner
{
protected StringBuilder Builder;
public StringJoiner()
{
Builder = new StringBuilder();
}
}
(Buiderをprotectedと定義し、いつかStering Joinerを引き継いで「観客をゆらす」ことが必要かもしれないと期待する)StringJoinerはどうやって先ほどのコードを実現しますか?
1.暗黙的な変換
例えば:
StringJoiner s = string.Empty;
の答えは:
public static implicit operator StringJoiner(string value)
{
StringJoiner text = new StringJoiner();
text.Builder.Append(value);
return text;
}
(新規オブジェクトを作成して、SteringBuilderのApppendメソッドに値を移す)2.操作子をリロードする
例えば:
s += "Bruce";
の答えは:
public static StringJoiner operator +(StringJoiner self, string value)
{
self.Builder.Append(value);
return self;
}
(StringJoinerとstringタイプを実現するには、演算子「+」で操作できます.同様に、StringBuiderに文字列を渡すApppend方法です.)より一般的にするために、他のタイプとの接続が実現される場合:
s += 123;
s += 0.314;
s += 'c';
したがって、Stering Joiner+Objectを積載しなければなりません.
public static StringJoiner operator +(StringJoiner self, object value)
{
self.Builder.Append(value);
return self;
}
最後に、StringJoinerの「ゆらゆら」レベルをさらに上にするためには、String Joinerのオブジェクトは、stringタイプに暗黙的に変換することができる必要がある.
public static implicit operator string(StringJoiner value)
{
return value.ToString();
}
public override string ToString()
{
return this.Builder.ToString();
}
もちろん、この時点でStringJoinerは十分です.もっと徹底的な「ゆらゆら」は本文の目的ではありません.StringJoinerはstringの代わりをしたいのではなく、StringBuiderの代わりをしたいのではなく、むしろ私はSteringBuiderを使うことに賛成しています.しかし、「string+=」によってもたらされる悲惨なコードを再構築したいなら、Stering Joinerを使いましょう.
性能テスト
性能カウンタ:CodeTimer(XP版)
テストコード(3つの異なる方法で1万回の文字列を綴じ合わせ、1万回の整数を綴じ合わせ、10回以上の操作を繰り返す):
static void Main(string[] args)
{
CodeTimer.Time("", 1, () => { });
// +=
CodeTimer.Time("NormalString", 10, () => NormalString());
//StringJoiner
CodeTimer.Time("StringJoiner", 10, () => StringJoiner());
//StringBuilder
CodeTimer.Time("StringBuilder", 10, () => StringBuilder());
Console.WriteLine("continue...");
Console.Read();
}
//
const int stringLength = 10000;
static void NormalString()
{
string s = string.Empty;
for (int i = 0; i < stringLength; i++)
s += "A";//
s = string.Empty;
for (int i = 0; i < stringLength; i++)
s += 1;//
string result = s;
}
static void StringJoiner()
{
StringJoiner s = string.Empty;
for (int i = 0; i < stringLength; i++)
s += "A";
s = string.Empty;
for (int i = 0; i < stringLength; i++)
s += 1;
string result = s;
}
static void StringBuilder()
{
StringBuilder s = new StringBuilder(string.Empty);
for (int i = 0; i < stringLength; i++)
s.Append("A");
s = new StringBuilder(string.Empty);
for (int i = 0; i < stringLength; i++)
s.Append(1);
string result = s.ToString();
}
一回のテスト結果:
NormalString
Time Elapsed: 667ms
Time Elapsed (one time):66ms
CPU time: 671,875,000ns
CPU time (one time): 67,187,500ns
Gen 0: 1908
Gen 1: 0
Gen 2: 0
StringJoiner
Time Elapsed: 19ms
Time Elapsed (one time):1ms
CPU time: 15,625,000ns
CPU time (one time): 1,562,500ns
Gen 0: 3
Gen 1: 0
Gen 2: 0
StringBuilder
Time Elapsed: 19ms
Time Elapsed (one time):1ms
CPU time: 15,625,000ns
CPU time (one time): 1,562,500ns
Gen 0: 3
Gen 1: 0
Gen 2: 0
上の図からは、StringJoinerとStringBuiderの性能はフラットであり、それらはいずれも第一の方法よりもはるかにリードしていることが分かります.