12

System.Reflection.Emit現在、コード生成に関する問題に取り組んでいます。私はdefault(SomeType)、C# で使用する場所でどの CIL を出力するかを理解しようとしています。

Visual Studio 11 Beta からいくつかの基本的な実験を実行しました。JustDecompiledefault(bool)は、 、default(string)、およびの次の CIL 出力を示していますdefault(int?

.locals init (
    [0] bool                                         V_0,
    [1] string                                       V_1,
    [2] valuetype [mscorlib]System.Nullable`1<int32> V_2    
)

// bool b = default(bool);
ldc.i4.0
stloc.0

// string s = default(string);
ldnull
stloc.1

// int? ni = default(int?);
ldloca.s V_2
initobj valuetype [mscorlib]System.Nullable`1<int32>

これから判断するとdefault(T)、コンパイラによって、指定された型に最も適した CIL に解決されるようです。


次に、3 つの一般的な方法を使用して、より一般的なケースで何が起こるかを確認しました。

T CreateStructDefault<T>() where T : struct { return default(T); }
T CreateClassDefault<T>()  where T : class  { return default(T); }
T CreateClassNull<T>()     where T : class  { return null;       }

3 つのメソッドはすべて同じ CIL メソッド本体を生成します。

.locals init (
    [0] !!T V_0,
    [1] !!T V_1
)

IL_0000: nop    
IL_0001: ldloca.s V_1
IL_0003: initobj !!T
IL_0009: ldloc.1
IL_000a: stloc.0
IL_000b: br.s IL_000d
IL_000d: ldloc.0
IL_000e: ret

質問:

default(SomeType)これらすべてから、C#は CIL に最もよく対応していると結論付けることができますか?

  • initobj非プリミティブ型 ( string? を除く)
  • ldc.iX.0//ldnullプリミティブ型の場合 (プラスstring)?

そして、なぜだけではなくCreateClassNull<T>に変換されるのでしょうか? 結局のところ、(参照型でもある)に対して発行されました。ldnullinitobjldnullstring

4

2 に答える 2

15

これらすべてから、C#は非プリミティブ型default(SomeType)の CIL と最も密接に対応し、プリミティブ型は などと結論付けられますか?initobjldc.i4.0ldnull

これは合理的な要約ですが、それについて考えるより良い方法は次のとおりです。C# コンパイラがコンパイル時default(T)の定数として分類する場合、定数の値が発行されます。これは、数値型の場合はゼロ、bool の場合は false、参照型の場合は null です。定数として分類されない場合は、(1) 一時変数を出力し、(2) 一時変数のアドレスを取得し、(3) そのアドレスを介してその一時変数を initobj し、(4) 一時変数の値が必要なときにスタックに。

なぜCreateClassNull<T>ldnull に変換するだけでなく、代わりに initobj に変換するのですか?

さて、あなたのやり方でそれを行い、何が起こるか見てみましょう:

... etc
.class private auto ansi beforefieldinit P
       extends [mscorlib]System.Object
{
  .method private hidebysig static !!T  M<class T>() cil managed
  {
    .maxstack  1
    ldnull
    ret
  } 
  ... etc

...

D:\>peverify foo.exe

Microsoft (R) .NET Framework PE Verifier.  Version  4.0.30319.17379
Copyright (c) Microsoft Corporation.  All rights reserved.

[IL]: Error: 
[d:\foo.exe : P::M[T]]
[offset 0x00000001]
[found Nullobjref 'NullReference']     
[expected (unboxed) 'T'] 
Unexpected type on the stack.
1 Error(s) Verifying d:\foo.exe

それがおそらく私たちがそれをしない理由でしょう。

于 2012-05-01T16:38:14.083 に答える
1

はい、そうdefaultです。0基本的に(または同等のもの)の単なる構文糖衣であると推測するのは正しいです。

于 2012-05-01T15:59:20.297 に答える