キャストと as
2chがプロパイダ規制食らってて書けないからここにメモっとく。
キャストと as の速度の問題。
普通のキャストと as は、ちゃんと型変換できるなら得られる結果は一緒で、失敗時には、
- キャスト: 例外発生
- as: null を返す
で、例外の throw ってのはかなり重たい処理で、型変換に失敗する可能性があるときは as にする方が大体パフォーマンスがいい。
じゃあ、100%型変換できるとわかってる場合はどう?という話に。
IL Disasem して調べてみると、単に、命令が1個違うだけだった↓。
- キャスト: castclass 命令
- as: isinst 命令
命令の差でパフォーマンスの違い推測できないんで、ここは実測。forループの中でキャストかasするだけの関数書いて、
Stopwatch sw = new Stopwatch(); sw.Reset(); sw.Start(); TestCast(N); Console.Write("{0}\n", sw.ElapsedTicks); sw.Reset(); sw.Start(); TestAs(N); Console.Write("{0}\n", sw.ElapsedTicks);
ってやってみたら、何度やってみても、順番入れ替えてみても、ただのキャストの方が1割程度速い。
まあ、100%キャストできることがわかってるケースなんて、大半は generics 使えばキャスト不要になりそうな気がしなくもない。
その他細々
ちなみに、型変換できなかった場合のコストは
- as: if(obj != null) を追加しても処理が倍程度に増えるだけ
- キャスト: 例外が発生すると 2ケタ・3ケタ遅い
あと、as と is の関係、
B b = new D(); // D extends B D d = b as D; if (d != null) ...
と
B b = new D(); // D extends B if (b is D) ...
がほとんど同じコードになってた。
IL の isinst 命令は C# の as 相当の命令で、is の方は isinst + null 比較(as + if文)になるっぽい。