2012-02-25 2 views

答えて

13

を書くことができます

if(!dictionary.Remove("plugin-01")) { 
    MessageBox.Show("Error: plugin-01 does not exist!"); 
} 

ような何かを行うことができます)

void Main() 
{ 
    Bar(); 
    Baz(); 
} 

bool Bar() 
{ 
    return true; 
} 

void Baz() 
{ 
    Console.WriteLine("placeholder"); 
} 

これは、次のILを生成します。

IL_0000: ldarg.0  
IL_0001: call  UserQuery.Bar 
IL_0006: pop   //remove current value from evaluation stack 
IL_0007: ldarg.0  
IL_0008: call  UserQuery.Baz 


Bar: 
IL_0000: ldc.i4.1  
IL_0001: ret  

Baz: 
IL_0000: ldstr  "placeholder" 
IL_0005: call  System.Console.WriteLine 
IL_000A: ret 

Barが呼び出され、評価スタックからブール値の戻り値を削除するポップが表示されます。これはどこにもありません。例を更新してBaz()への別のメソッド呼び出しを追加しなければならなかった。さもなければ、プログラムが終了するので、popは出されないだろう。

今の私たちが実際に戻り値を使用する場合を見てみましょう:

void Main() 
{ 
    bool foo = Bar(); 
    Console.WriteLine(foo); 
} 

bool Bar() 
{ 
    return true; 
} 

これは、次のILを生成します。

IL_0000: ldarg.0  
IL_0001: call  UserQuery.Bar 
IL_0006: stloc.0 //pops current value from evaluation stack, stores in local var 
IL_0007: ldloc.0  
IL_0008: call  System.Console.WriteLine 

Bar: 
IL_0000: ldc.i4.1  
IL_0001: ret 

IL_007を含めた後、すべてとあるSystem.Console.WriteLine一部を無視します - コンパイラが変数の使用を最適化しないように、それを追加するだけでした。 Barメソッド呼び出しの結果が評価スタックからポップされ、ローカル変数fooに格納されていることがわかります。それは戻り値を取得して取り除くpopか、結果を変数に代入するためにstloc.0のいずれかです。

したがって、メソッド呼び出しの結果が必要ない場合は、結果を無視するだけです。結果を変数に代入してその変数を使用しなくても、コンパイラは変数と割り当てを完全に最適化することができます(少なくともデバッグモードではデバッグ経験を向上させるためにほとんどの最適化が無効になります)。

+0

'Console.WriteLine(foo)'を削除すると、ILは最初の例と同じになるはずですか? – enzom83

+1

はい、それはある - 変数 'foo'が使用されることはありませんので、それは(おそらく)離れて最適化されています。 「これは、次のILを生成し、」あなたの最初で – BrokenGlass

+0

は、私はあなたが呼び出しに続くPOP命令を含めるべきだと思います。 - しかし、あなたはありLinqPadによって生成されるよう、私は完全なIL出力を示した。これは、メソッドの結果は、MSILをスタック上にあり、呼び出し側が –

3

戻り値は、使用しない場合は無視されます。

あなたは気にしない場合、あなたは安全のは、それがLinqPadの(礼儀を生産している簡単な例とILコードを見てみましょう

dictionary.Remove("plugin-01"); 
1

呼び出し部分は同じですが、割り当て部分はILでスキップされます。見てください - ここでは簡単なプログラムの解体である:解体はこのようになります

var d = new Dictionary<int,int>(); 
bool a = d.Remove(5); 
d.Remove(6); 

bool a = d.Remove(5); 
00000057 mov   ecx,dword ptr [ebp-40h] 
0000005a mov   edx,5 
0000005f cmp   dword ptr [ecx],ecx 
00000061 call  69106A00 
// Here is the assignment part 
00000066 mov   dword ptr [ebp-4Ch],eax 
00000069 movzx  eax,byte ptr [ebp-4Ch] 
0000006d mov   dword ptr [ebp-44h],eax 
    d.Remove(6); 
00000070 mov   ecx,dword ptr [ebp-40h] 
00000073 mov   edx,6 
00000078 cmp   dword ptr [ecx],ecx 
0000007a call  69106A00 

トップの4行は共通しています。最初のコールから最後の3行が割り当てを処理します。 2回目の呼び出しの分解では欠落しています。

関連する問題