IteratorブロックがILでtry-faultを生成します
質問
イテレータブロックで実験した後、生成されたILコードが期待したものではないことに気付きました。 try-finallyブロックの代わりに、try-faultブロックが生成されますが、これは私が見たことがありません。コンパイラーは、「手書き」C#でfaultキーワードの使用を許可していないことに気付きました。
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<*>,
[1] int32 CS$4$0001,
[2] string CS<*>$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
}
興味深い行は、障害ハンドラーが指定されているILの最後の行です。通常のtry-finallyブロックでは、finallyハンドラーが指定されています。
解決
はい、Finalブロックは常にフレームの終了時に実行されます。障害ブロックは、例外がフレームを超えて巻き戻された場合にのみ実行されます。 MoveNextの障害ブロックは、ReadAllLinesイテレーターのtryブロックからスローされた例外の場合に使用するセマンティクスを保持します。イテレータからの通常の終了時に使用セマンティクスを保持するには、他のメカニズムを使用する必要があります。
所属していません StackOverflow