あなたはすでに回答を受け入れていますが、私はすでに調査を行っているので、投稿することにします。
リリース ビルドを実行するときに出力 IL を確認すると、2 つのセットアップの間にほとんど違いはありません。
最初の「最適化されていない」呼び出しからの出力 IL は次のようになります。
// Code size 47 (0x2f)
.maxstack 8
IL_0000: ldarg.0
IL_0001: isinst TestApp.Program/Car
IL_0006: brfalse.s IL_002e
IL_0008: ldarg.0
IL_0009: isinst TestApp.Program/Car
IL_000e: callvirt instance int32 TestApp.Program/Car::get_numWheels()
IL_0013: ldc.i4.4
IL_0014: bne.un.s IL_002e
IL_0016: ldarg.0
IL_0017: isinst TestApp.Program/Car
IL_001c: callvirt instance bool TestApp.Program/Car::get_hasGas()
IL_0021: brfalse.s IL_002e
IL_0023: ldarg.0
IL_0024: isinst TestApp.Program/Car
IL_0029: callvirt instance void TestApp.Program/Car::drive()
IL_002e: ret
2 番目の「最適化された」呼び出しからの出力 IL は次のようになります。
// Code size 34 (0x22)
.maxstack 2
.locals init ([0] class TestApp.Program/Car c)
IL_0000: ldarg.0
IL_0001: isinst TestApp.Program/Car
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: brfalse.s IL_0021
IL_000a: ldloc.0
IL_000b: callvirt instance int32 TestApp.Program/Car::get_numWheels()
IL_0010: ldc.i4.4
IL_0011: bne.un.s IL_0021
IL_0013: ldloc.0
IL_0014: callvirt instance bool TestApp.Program/Car::get_hasGas()
IL_0019: brfalse.s IL_0021
IL_001b: ldloc.0
IL_001c: callvirt instance void TestApp.Program/Car::drive()
IL_0021: ret
isinst
「最適化されていない」呼び出しで行われている追加の呼び出しがあります。これは最適化して取り除くのに適していますが、関数の実行時間に実質的な影響を与えることはありません。
とはいえ、C# コードは読みやすいため、「最適化」を行います。これは、パフォーマンスのマイクロ最適化よりも重要です (コードをプロファイリングし、パフォーマンスのボトルネックを最適化する必要があると判断するまでは)。
(また、スタックが少し大きくなりますが、高速ですぐにクリーンアップされるスタックの増加であり、6 バイトしかないため、非常にマイナーです。)