2009-08-01 6 views
11

イテレータブロックを試した後、私は生成されたILコードが期待通りではないことに気付きました。 try-finallyブロックの代わりにtry-faultブロックが生成されますが、これは見たことがありません。私はコンパイラが 'handwritten' C#でfaultキーワードを使用できないことに気づいた。イテレータブロックはILで試行フォルトを生成します

2の間に違いはありますか?

C#コード:

static IEnumerable<string> ReadAllLines(string fileName) 
{ 
    using (var file = System.IO.File.OpenText(fileName)) 
    { 
     string s; 
     while ((s = file.ReadLine()) != null) 
     { 
      yield return s; 
     } 
    } 
} 

MSILコード:

.method private hidebysig newslot virtual final instance bool MoveNext() cil managed 
{ 
    .override [mscorlib]System.Collections.IEnumerator::MoveNext 
    .maxstack 3 
    .locals init (
     [0] bool CS$1$0000, 
     [1] int32 CS$4$0001, 
     [2] string CS$0$0002, 
     [3] bool CS$4$0003) 
    L_0000: ldarg.0 

    // try body 

    L_008d: leave.s L_0097 
    L_008f: ldarg.0 
    L_0090: call instance void ConsoleApplication2.Program/<ReadAllLines>d__0::System.IDisposable.Dispose() 
    L_0095: nop 
    L_0096: endfinally 
    L_0097: nop 
    L_0098: ldloc.0 
    L_0099: ret 
    .try L_0000 to L_008f fault handler L_008f to L_0097 
} 

興味深い行は、通常のtry-最終的に遮断する障害ハンドラーが指定されているILの最後の行であり、 finallyハンドラが指定されました。

+1

これは特に.net-4.0でタグ付けされていますか?これはバージョン間で変更されましたか? –

答えて

8

はい、finallyブロックは常にフレームの終了時に実行されます。フォルトブロックは、例外がフレームを過ぎて巻き戻された場合にのみ実行されます。 MoveNextのフォールトブロックは、ReadAllLinesイテレータのtryブロックからスローされた例外の場合に使用するセマンティクスを保持します。イテレータからの通常の終了時にセマンティクスを保持するには、他のメカニズムを使用する必要があります。

+0

したがって、障害のDisposeは、try部分の例外を処理するときにのみ呼び出されます。 通常のdisposeは、生成されたIEnumeratorのDisposeメソッドによって処理されます。 –

関連する問題