有人能否创建一个简短的示例,除非应用了[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
否则会出错?
我刚刚在MSDN上运行了这个示例,即使我注释掉了ReliabilityContract属性,也无法让它崩溃。最终似乎总是被调用。
有人能否创建一个简短的示例,除非应用了[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
否则会出错?
我刚刚在MSDN上运行了这个示例,即使我注释掉了ReliabilityContract属性,也无法让它崩溃。最终似乎总是被调用。
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
class Program {
static bool cerWorked;
static void Main( string[] args ) {
try {
cerWorked = true;
MyFn();
}
catch( OutOfMemoryException ) {
Console.WriteLine( cerWorked );
}
Console.ReadLine();
}
unsafe struct Big {
public fixed byte Bytes[int.MaxValue];
}
//results depends on the existance of this attribute
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
unsafe static void StackOverflow() {
Big big;
big.Bytes[ int.MaxValue - 1 ] = 1;
}
static void MyFn() {
RuntimeHelpers.PrepareConstrainedRegions();
try {
cerWorked = false;
}
finally {
StackOverflow();
}
}
}
当 MyFn
被 jit 编译时,它会尝试从 finally
块创建一个 ConstrainedRegion
。
在没有 ReliabilityContract
的情况下,无法形成适当的 ConstrainedRegion
,因此会生成常规代码。栈溢出异常会在调用 Stackoverflow
(try 块执行后)时抛出。
如果有 ReliabilityContract
,则可以形成一个 ConstrainedRegion
,并且 finally
块中方法的堆栈要求可以提升到 MyFn
中。现在,栈溢出异常会在调用 MyFn
时抛出(在 try 块执行之前)。
System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions();
try
{
// this is not constrained
}
catch (Exception e)
{
// this IS a CER
}
finally
{
// this IS ALSO a CER
}
SafeHandles
以确保它们被关闭。这包括任何导致操作系统SafeHandle(GDI+、文件等)的P/Invoke。如果在Windows中泄漏句柄,很快就会遇到麻烦。 - Jeremy您是否在调试器下运行MSDN示例?我认为当您在调试器中执行时,CER无法工作,因为调试器本身会改变执行方式。
如果您以优化的发布模式构建并运行应用程序,则应该能够看到它失败。
虽然我没有具体的例子给你,但我认为你忽略了在方法内部使用try..finally块来保证成功的重点。声明该方法总是成功的意思是无论执行过程中发生什么(异常),都会采取措施确保在方法返回时所访问的数据处于有效状态。如果没有try..finally,你将无法确保任何事情,并且可能意味着你想要发生的操作只有一半会发生。因此,Cer.Success并不实际上保证成功,它只表示作为开发人员的你保证成功。
查看这个页面,了解Success和MayFail状态之间差异的解释,因为它涉及到一个Array.CopyTo方法:http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx
CER 属性是文档的一种方式。它们确实会影响 CLR 在某些情况下执行代码的方式,但我相信它们(或缺乏它们)在当前版本的 .NET 中永远不会导致错误。
它们大多数是“为将来保留”的。