2つのオブジェクトがあり、それぞれを比較するために等式演算子をオーバーロードした場合、?の使用法にうんざりする必要があります。演算子(たとえばfirstObject?.MyProperty == secondObject?.MyProperty
)20〜30のプロパティでそれを使用することになった場合はどうなりますか?
基本的に、多くのプロパティを持つ大きなオブジェクトの場合、次の比較を行う方がよいでしょう
(firstObject == null && secondObject == null || !(firstObject == null ^ secondObject == null))
&& (<property comparisons without ?>)
または単に
<property comparisons with ?>
ありがとうございました。
ボンネットの下では、それらは異なります。?.
より読みやすいと速い(それはそう)。
まず、このサンプル(ターゲティング.NET Framework 4.7.2
)について考えてみましょう。
class Program { class Foo { public Foo Bar {get; セットする; } } static void Main(string [] args) { var foo = new Foo(); var t0 = DateTime.UtcNow.Ticks; for(int i = 0; i <1000000000; i ++) { UsingElvisOperator(foo); // UsingIfsAndButs(foo); } var t1 = DateTime.UtcNow.Ticks; Console.WriteLine($ "経過時間:{(t1--t0)/ 10000}ミリ秒"); } private static void UsingIfsAndButs(Foo foo) { if(foo?.Bar?.Bar?.Bar!= null) { Console.WriteLine( "OK"); } } private static void UsingElvisOperator(Foo foo) { if(foo!= null && foo.Bar!= null && foo.Bar.Bar!= null && foo.Bar.Bar.Bar!= null) { Console.WriteLine( "OK"); } } }
プラットフォームRelease
用のモードでコンパイルしAny CPU
ます。それでは、ildasm.exe
を使用して生成されたものを逆コンパイルしましょう。
以下のための説明書エルビス演算子:
.method private hidebysig static void UsingElvisOperator(class OperatorTest.Program/Foo foo) cil managed
{
// Code size 53 (0x35)
.maxstack 8
IL_0000: ldarg.0
IL_0001: brfalse.s IL_0034
IL_0003: ldarg.0
IL_0004: callvirt instance class OperatorTest.Program/Foo OperatorTest.Program/Foo::get_Bar()
IL_0009: brfalse.s IL_0034
IL_000b: ldarg.0
IL_000c: callvirt instance class OperatorTest.Program/Foo OperatorTest.Program/Foo::get_Bar()
IL_0011: callvirt instance class OperatorTest.Program/Foo OperatorTest.Program/Foo::get_Bar()
IL_0016: brfalse.s IL_0034
IL_0018: ldarg.0
IL_0019: callvirt instance class OperatorTest.Program/Foo OperatorTest.Program/Foo::get_Bar()
IL_001e: callvirt instance class OperatorTest.Program/Foo OperatorTest.Program/Foo::get_Bar()
IL_0023: callvirt instance class OperatorTest.Program/Foo OperatorTest.Program/Foo::get_Bar()
IL_0028: brfalse.s IL_0034
IL_002a: ldstr "OK"
IL_002f: call void [mscorlib]System.Console::WriteLine(string)
IL_0034: ret
} // end of method Program::UsingElvisOperator
そして、if-checksの説明:
.method private hidebysig static void UsingIfsAndButs(class OperatorTest.Program/Foo foo) cil managed
{
// Code size 49 (0x31)
.maxstack 8
IL_0000: ldarg.0
IL_0001: brtrue.s IL_0006
IL_0003: ldnull
IL_0004: br.s IL_0024
IL_0006: ldarg.0
IL_0007: call instance class OperatorTest.Program/Foo OperatorTest.Program/Foo::get_Bar()
IL_000c: dup
IL_000d: brtrue.s IL_0013
IL_000f: pop
IL_0010: ldnull
IL_0011: br.s IL_0024
IL_0013: call instance class OperatorTest.Program/Foo OperatorTest.Program/Foo::get_Bar()
IL_0018: dup
IL_0019: brtrue.s IL_001f
IL_001b: pop
IL_001c: ldnull
IL_001d: br.s IL_0024
IL_001f: call instance class OperatorTest.Program/Foo OperatorTest.Program/Foo::get_Bar()
IL_0024: brfalse.s IL_0030
IL_0026: ldstr "OK"
IL_002b: call void [mscorlib]System.Console::WriteLine(string)
IL_0030: ret
} // end of method Program::UsingIfsAndButs
明らかに、生成された命令は異なります。
私のマシンで2つのメソッドを10億回実行すると、次の結果が得られます。
UsingElvisOperator: 1704 ms
UsingIfsAndButs: 2815 ms
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加