はじめに
C#で型変換に使う主な5つの方法の速さを比べました。
結論
()キャストを使う場合、例外が発生すると極端に遅くなるが、全く例外が発生しないケースでは最速でした。
is, asの型変換はどんなケースでもそれなりの速さが出るようです。
環境
Windows 10 Home, AMD Ryzen 5 3500 6-Core Processor(3.59 GHz), 16GB Memory, Visual Studio 2019, .Net Core 3.1
計測コード
classA{publicA(strings){member=s;}stringmember;}classB{publicB(strings){member=s;}stringmember;}//tryとcatchで囲って()キャストする方法staticvoidCast(object[]vs){foreach(objectoinvs){try{Av=(A)o;}catch{}}}//asキーワードで変換してからnullチェックする方法staticvoidAsIf(object[]vs){foreach(objectoinvs){Av=oasA;if(v==null){}}}//isキーワードで変換できるかをチェックし、そのまま変換する方法staticvoidIfIs(object[]vs){foreach(objectoinvs){if(oisAv){}}}//isキーワードでチェックしてから()キャストする方法staticvoidIfIsCast(object[]vs){foreach(objectoinvs){if(oisA){Av=(A)o;}}}//isキーワードでチェックしてからasキーワードで変換する方法staticvoidIfIsAs(object[]vs){foreach(objectoinvs){if(oisA){Av=oasA;}}}//5つの変換方法を試すstaticvoidTryMethods(intpercentageOfA){intseparator=(int)(percentageOfA/100f*ss.Length);object[]vs=ss.Select((s,i)=>i<separator?(object)newA(s):newB(s)).ToArray();Console.WriteLine($"{percentageOfA}%");Console.WriteLine($"Cast:\t\t{Measure(count,()=>Cast(vs))}");Console.WriteLine($"AsIf:\t\t{Measure(count,()=>AsIf(vs))}");Console.WriteLine($"IfIs:\t\t{Measure(count,()=>IfIs(vs))}");Console.WriteLine($"IfIsCast:\t{Measure(count,()=>IfIsCast(vs))}");Console.WriteLine($"IfIsAs:\t\t{Measure(count,()=>IfIsAs(vs))}");Console.WriteLine();}staticintcount=3000;staticstring[]ss=newstring[10000000];//エントリポイントpublicstaticvoidEntry(){Randomrandom=newRandom();for(inti=0;i<ss.Length;i++){intlength=random.Next(10);for(intj=0;j<length;j++){ss[i]+=(char)random.Next('A','z');}}Console.WriteLine($"count:\t{count}");Console.WriteLine($"length:\t{ss.Length}");Console.WriteLine();TryMethods(0);TryMethods(20);TryMethods(40);TryMethods(60);TryMethods(80);TryMethods(100);}//関数の処理にかかる時間を計測するpublicstaticTimeSpanMeasure(intcount,Actionaction){DateTimetime=DateTime.Now;for(inti=0;i<count;i++){action();}returnDateTime.Now-time;}
結果
型変換に失敗する参照が含まれている場合
例外処理が重すぎたため、以下の数値設定でひとまず測りました。
count = 1
length = 10000
表の左上の値は型変換に失敗する参照が含まれている割合です。
時間の単位は秒です。
0% | 1回目 | 2回目 | 3回目 | 平均 |
---|
Cast | 71.1655179 | 71.8009120 | 71.6555776 | 71.5406692 |
AsIf | 0.0002877 | 0.0003214 | 0.0002501 | 0.0002864 |
IfIs | 0.0002317 | 0.0001495 | 0.0001622 | 0.0001811 |
IfIsCast | 0.0001465 | 0.0001404 | 0.0002372 | 0.0001747 |
IfIsAs | 0.0001366 | 0.0001362 | 0.0001423 | 0.0001384 |
20% | 1回目 | 2回目 | 3回目 | 平均 |
---|
Cast | 56.6513413 | 56.5845480 | 57.0564668 | 56.7641187 |
AsIf | 0.0000406 | 0.0000440 | 0.0000363 | 0.0000403 |
IfIs | 0.0000344 | 0.0000424 | 0.0000406 | 0.0000391 |
IfIsCast | 0.0000363 | 0.0000399 | 0.0000358 | 0.0000373 |
IfIsAs | 0.0000407 | 0.0000351 | 0.0000353 | 0.0000370 |
40% | 1回目 | 2回目 | 3回目 | 平均 |
---|
Cast | 42.7042395 | 42.6855280 | 42.9887469 | 42.7928381 |
AsIf | 0.0000365 | 0.0000365 | 0.0000361 | 0.0000364 |
IfIs | 0.0000364 | 0.0000376 | 0.0000324 | 0.0000355 |
IfIsCast | 0.0000342 | 0.0000369 | 0.0000368 | 0.0000360 |
IfIsAs | 0.0000425 | 0.0000392 | 0.0000337 | 0.0000385 |
60% | 1回目 | 2回目 | 3回目 | 平均 |
---|
Cast | 28.6295313 | 28.4973504 | 28.7604727 | 28.6291181 |
AsIf | 0.0000340 | 0.0000340 | 0.0000343 | 0.0000341 |
IfIs | 0.0000317 | 0.0000315 | 0.0000325 | 0.0000319 |
IfIsCast | 0.0000490 | 0.0000369 | 0.0000372 | 0.0000410 |
IfIsAs | 0.0000315 | 0.0000306 | 0.0000311 | 0.0000311 |
80% | 1回目 | 2回目 | 3回目 | 平均 |
---|
Cast | 14.4235740 | 14.4582490 | 14.4788299 | 14.4535510 |
AsIf | 0.0000315 | 0.0000325 | 0.0000309 | 0.0000316 |
IfIs | 0.0000273 | 0.0000329 | 0.0000315 | 0.0000306 |
IfIsCast | 0.0000304 | 0.0000342 | 0.0000342 | 0.0000329 |
IfIsAs | 0.0000322 | 0.0000363 | 0.0000304 | 0.0000330 |
100% | 1回目 | 2回目 | 3回目 | 平均 |
---|
Cast | 0.0000244 | 0.0000241 | 0.0000264 | 0.0000250 |
AsIf | 0.0000286 | 0.0000272 | 0.0000259 | 0.0000272 |
IfIs | 0.0000263 | 0.0000262 | 0.0000261 | 0.0000262 |
IfIsCast | 0.0000303 | 0.0000358 | 0.0000300 | 0.0000320 |
IfIsAs | 0.0000303 | 0.0000302 | 0.0000301 | 0.0000302 |
型変換に失敗する参照が含まれていない場合
上の結果でいう100%だけを以下の数値設定で測りました。
count = 3000
length = 10000000
100% | 1回目 | 2回目 | 3回目 | 平均 |
---|
Cast | 73.9517405 | 74.0026143 | 74.1104895 | 74.0216148 |
AsIf | 81.3793428 | 81.5171491 | 81.4947477 | 81.4637465 |
IfIs | 81.9090815 | 82.2008835 | 81.9648811 | 82.0249487 |
IfIsCast | 93.9863807 | 94.0810441 | 87.0868509 | 91.7180919 |
IfIsAs | 93.9113493 | 94.2150005 | 87.0688733 | 91.7317410 |
()キャストは最速といっても気持ち速い程度のようです。
IfIsCastとIfIsAsは値が比較的安定していないので、実行状況によって速さが変わりやすいのかもしれません。