如何CIL'故障'条款从C#'抓'的条款有什么不同? [英] How are CIL 'fault' clauses different from 'catch' clauses in C#?
问题描述
按照 CLI标准(分区IIA,第18章)和MSDN对于 System.Reflection.ExceptionHandlingClauseOptions
枚举,有四种不同类型的异常处理模块:
- 捉条款:的赶指定类型的所有对象。的
- 过滤器条款:只有当过滤器成功进入处理程序。 的
- 最后条款:。处理所有异常和正常退出的
- 故障条款:处理所有异常,但不正常的退出。的
鉴于这些简单的解释(从CLI标准的引用,顺便说一句),这些都应该映射到C#如下:
- 抓—
赶上(FooException){...}
- 过滤器—在C#中不存在(但在VB.NET为
捕捉FooException当booleanExpression
) - 最后—
终于{...}
- 故障—
赶上{...}
实验:
一个简单的实验表明,这种映射是不是.NET的C#编译器确实:
//使用System.Linq的;
//使用的System.Reflection;
静态布尔IsCatchWithoutTypeSpecificationEmittedAsFaultClause()
{
试
{
返回MethodBase
.GetCurrentMethod()
.GetMethodBody()
.ExceptionHandlingClauses
。任何(第=> clause.Flags == ExceptionHandlingClauseOptions.Fault);
}
捕捉//< - 这就是上面的代码检查
{
扔;
}
}
这方法的返回值假
。也就是说,赶上{...}
尚未发出的一个错误的条款。
一个类似的实验表明,在事实上,一个catch子句发出( clause.Flags == ExceptionHandlingClauseOptions.Clause
),即使没有异常的类型已经被指定。
问题:
- 如果
赶上{...}
真的是一个catch子句,那么如何从catch子句不同故障的条款? - 请问C#编译器不断输出故障的条款呢?
有四种不同的异常处理模块:
- 捉条款:捕捉指定类型的所有对象的
- 过滤器条款:输入仅当过滤器成功处理程序。的
- 最后条款:处理所有异常和正常退出的
- 故障条款:。处理所有异常,但不正常的退出的
由于这些简单的解释(从CLI标准的引用,顺便说一句),这些都应该映射到C#如下:
- 捉&MDASH;
赶上(FooException){...}
- 过滤器&MDASH;在C#中不存在(但在VB.NET为
捕捉FooException当booleanExpression
)
- 最后&MDASH;
终于{...}
- 故障&MDASH;
赶上{...}
块引用>
这是你在哪里错了最后一道防线。再次阅读说明。
故障
和最后
实际上是相同的描述。它们之间的区别是,最后
总是进入,而故障
只有进入当控制离开尝试
通过一个例外。请注意,这意味着抓
块可能已经采取行动
如果你写在C#中:
{试
:
}赶上(SpecificException前){
$ ... b $ b} {赶上
:
}
再有就是没办法,如果控制通过
SpecificException
离开尝试
第三块将被输入。这就是为什么捕捉{}
不是故障
。
的映射According to the CLI standard (Partition IIA, chapter 18) and the MSDN reference page for the
System.Reflection.ExceptionHandlingClauseOptions
enum, there are four different kinds of exception handler blocks:
- catch clauses: "Catch all objects of the specified type."
- filter clauses: "Enter handler only if filter succeeds."
- finally clauses: "Handle all exceptions and normal exit."
- fault clauses: "Handle all exceptions but not normal exit."
Given these brief explanations (cited from the CLI Standard, btw.), these should map to C# as follows:
- catch —
catch (FooException) { … }
- filter — not available in C# (but in VB.NET as
Catch FooException When booleanExpression
)- finally —
finally { … }
- fault —
catch { … }
Experiment:
A simple experiment shows that this mapping is not what .NET's C# compiler really does:
// using System.Linq; // using System.Reflection; static bool IsCatchWithoutTypeSpecificationEmittedAsFaultClause() { try { return MethodBase .GetCurrentMethod() .GetMethodBody() .ExceptionHandlingClauses .Any(clause => clause.Flags == ExceptionHandlingClauseOptions.Fault); } catch // <-- this is what the above code is inspecting { throw; } }
This method returns
false
. That is,catch { … }
has not been emitted as a fault clause.A similar experiment shows that in fact, a catch clause was emitted (
clause.Flags == ExceptionHandlingClauseOptions.Clause
), even though no exception type has been specified.Questions:
- If
catch { … }
really is a catch clause, then how are fault clauses different from catch clauses?- Does the C# compiler ever output fault clauses at all?
解决方案there are four different kinds of exception handler blocks:
- catch clauses: "Catch all objects of the specified type."
- filter clauses: "Enter handler only if filter succeeds."
- finally clauses: "Handle all exceptions and normal exit."
- fault clauses: "Handle all exceptions but not normal exit."
Given these brief explanations (cited from the CLI Standard, btw.), these should map to C# as follows:
- catch —
catch (FooException) { … }
- filter — not available in C# (but in VB.NET as
Catch FooException When booleanExpression
)- finally —
finally { … }
- fault —
catch { … }
It's that last line where you went wrong. Read the descriptions again.
fault
andfinally
are described practically identically. The difference between them is thatfinally
is always entered, whereasfault
is only entered if control leaves thetry
via an exception. Note that this means that acatch
block may have already acted.If you write this in C#:
try { ... } catch (SpecificException ex) { ... } catch { ... }
Then there is no way that the third block will be entered if control leaves the
try
via aSpecificException
. That's whycatch {}
isn't a mapping forfault
.这篇关于如何CIL'故障'条款从C#'抓'的条款有什么不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!