0

C#内で、2つの異なる書き方で生成されるバイトコードに違いはありますか?私は同じことを期待しています:

作成されたオブジェクトを返す:

public MemoryStream GetStream() {
  MemoryStream s = new MemoryStream(this.GetBytes());
  return s;
}

リターン新:

public MemoryStream GetStream() {
  return new MemoryStream(this.GetBytes());
}

違いは最適化されますか? それとも、最初のほうが 2 番目よりもガベージ コレクションの影響を受けやすいのでしょうか? それとも、これはすべて個人的な好みですか?

4

4 に答える 4

1

IL コードを見ると、2 番目のバージョンは 1 番目よりも手順が少ないようです。

.method public hidebysig 
    instance class [mscorlib]System.IO.MemoryStream GetStream1 () cil managed 
{
    // Method begins at RVA 0x22c0
    // Code size 13 (0xd)
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.IO.MemoryStream s,
        [1] class [mscorlib]System.IO.MemoryStream CS$1$0000
    )

    IL_0000: nop
    IL_0001: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor()
    IL_0006: stloc.0
    IL_0007: ldloc.0
    IL_0008: stloc.1
    IL_0009: br.s IL_000b

    IL_000b: ldloc.1
    IL_000c: ret
} // end of method Form1::GetStream1

.method public hidebysig 
    instance class [mscorlib]System.IO.MemoryStream GetStream2 () cil managed 
{
    // Method begins at RVA 0x22dc
    // Code size 11 (0xb)
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.IO.MemoryStream CS$1$0000
    )

    IL_0000: nop
    IL_0001: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor()
    IL_0006: stloc.0
    IL_0007: br.s IL_0009

    IL_0009: ldloc.0
    IL_000a: ret
} // end of method Form1::GetStream2

それほど多くのことをしているようには見えませんが、それでもなお、さらにいくつかのステップがあります。

@Alexei Levenkov、これはコードのリリースバージョンです

.method public hidebysig 
    instance class [mscorlib]System.IO.MemoryStream GetStream1 () cil managed 
{
    // Method begins at RVA 0x2264
    // Code size 8 (0x8)
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.IO.MemoryStream s
    )

    IL_0000: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor()
    IL_0005: stloc.0
    IL_0006: ldloc.0
    IL_0007: ret
} // end of method Form1::GetStream1

.method public hidebysig 
    instance class [mscorlib]System.IO.MemoryStream GetStream2 () cil managed 
{
    // Method begins at RVA 0x2278
    // Code size 6 (0x6)
    .maxstack 8

    IL_0000: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor()
    IL_0005: ret
} // end of method Form1::GetStream2

まだ少し多いようです。

于 2013-06-28T07:38:29.277 に答える
1

Reflector を使用して、このために生成されたコードを検査する場合:

public MemoryStream GetStream(byte[] bytes)
{
    MemoryStream s = new MemoryStream(bytes);
    return s;
}

リリース ビルドの場合は、次のようになります。

.method public hidebysig instance class [mscorlib]System.IO.MemoryStream GetStream(uint8[] bytes) cil managed
{
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.IO.MemoryStream s)
    L_0000: ldarg.1 
    L_0001: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor(uint8[])
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: ret 
}

ご覧のとおり、C# コンパイラは余分な変数を最適化して取り除きました。

ただし、デバッグ ビルドの場合は次のようになります。

.method public hidebysig instance class [mscorlib]System.IO.MemoryStream GetStream(uint8[] bytes) cil managed
{
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.IO.MemoryStream s,
        [1] class [mscorlib]System.IO.MemoryStream CS$1$0000)
    L_0000: nop 
    L_0001: ldarg.1 
    L_0002: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor(uint8[])
    L_0007: stloc.0 
    L_0008: ldloc.0 
    L_0009: stloc.1 
    L_000a: br L_000f
    L_000f: ldloc.1 
    L_0010: ret 
}

明らかに、デバッグ中に検査したい場合に備えて、コンパイラはデバッグビルド用の余分な変数を最適化することはできません。

したがって、デバッグ目的で追加の変数を残しておきたい場合は、それで問題ありません。リリース ビルドには影響しません。

于 2013-06-28T07:40:25.387 に答える
1

結果として得られる最適化された JIT コードは同じになると思います。

オブジェクトの有効期間は戻り値を使用する人によって決定されるため、GC の動作にはまったく影響はありません (関数の終了前に値が使用されなくなった場合を考えているかもしれませんが、ここでは明らかにそうではありません-sすぐに返されますメソッドの実行の終了)。

s最適化されていない (デバッグ) ビルドの唯一の顕著な違いは、変数の値を確認できることです。

于 2013-06-28T07:40:43.117 に答える
0

2 つのコード スニペットはほとんど同じであり、パフォーマンスの違いはごくわずかであり、無視できるものであり、コード スタイルとメソッド機能の問題から選択する必要があります。メソッドがオブジェクトを返す以外に何もしないと想定されている場合は、2 番目のコード スニペットで十分ですが、オブジェクトを返す前にオブジェクトMemoryStreamに対して何らかの操作を実行する必要がある場合は、最初のコード スニペットを使用する必要があります。MemoryStreamガベージ コレクションに関しては違いはありません。

于 2013-06-28T07:39:52.330 に答える