例如,我很好奇,如果在下面的代码中,我可以保证要么Foo()
或Bar()
将被执行。
try {
... // Assume there is no return statement here
Foo();
} catch (Exception e) {
Bar();
}
我对finally
块非常熟悉,不需要对该功能进行解释。
我问是因为上面的代码由于存在 . 而在 Java 中无法Throwable
工作,我发现这是一个艰难的过程。
还有停止应用程序的“烧毁房屋”方法:
Environment.Exit(int code);
Environment.FailFast(string message);
Thread.CurrentThread.Abort();
AppDomain.Unload(AppDomain.CurrentDomain);
为了好玩,这是另一个:)
[DllImport("kernel32.dll",SetLastError = true)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte [] lpBuffer,
uint nSize,
out UIntPtr lpNumberOfBytesWritten);
var myProcess = Process.GetCurrentProcess();
var hProcess = myProcess.Handle;
var rnd = new Random();
while(true)
{
var writeTo = new IntPtr((int)rnd.Next(0, int.MaxValue));
var toWrite = new byte[1024];
UIntPtr written;
WriteProcessMemory(
hProcess,
writeTo,
toWrite,
(uint)toWrite.Length,
out written);
}
出于好奇和刺激,让我们带他们去试驾吧!
我们的试验台:
static void Main(string[] args)
{
Trace.Listeners.Add(new ConsoleTraceListener());
AppDomain.CurrentDomain.UnhandledException += OnNoes;
try
{
// INSERT BURN STATEMENT
Foo();
}
catch (Exception e)
{
Bar();
}
finally
{
Baz();
}
}
static void Foo()
{
Trace.WriteLine("I AM FOO!");
}
static void Bar()
{
Trace.WriteLine("I AM BAR!");
}
static void Baz()
{
Trace.WriteLine("I AM BAZ!");
}
static void OnNoes(object sender, UnhandledExceptionEventArgs e)
{
Trace.WriteLine("OhNoes!");
}
结果!
烧伤声明:
Thread.CurrentThread.Abort();
输出:
I AM BAR!
I AM BAZ!
烧伤声明:
AppDomain.Unload(AppDomain.CurrentDomain);
输出:
I AM BAR!
I AM BAZ!
烧伤声明:
Environment.Exit(-1);
输出:
Nothing! No trace output at all!
烧伤声明:
Environment.FailFast("Burn!!!");
输出:
Application crash! A FatalExecutionEngineError was thrown,
which was not caught by any block/handler. No trace output.
所以你去吧!什么?我错过了一个?
烧伤声明:
Splode();
其中“Splode”是:
static void Splode()
{
var myProcess = Process.GetCurrentProcess();
var hProcess = myProcess.Handle;
var rnd = new Random();
while (true)
{
var writeTo = new IntPtr((int)rnd.Next(0, int.MaxValue));
var toWrite = new byte[1024];
UIntPtr written;
WriteProcessMemory(
hProcess,
writeTo,
toWrite,
(uint)toWrite.Length,
out written);
}
}
输出:
Application crash! A FatalExecutionEngineError was thrown,
which was not caught by any block/handler. No trace output.
Crashed Visual Studio while running attached!
是的...最明显的是await
, yield break
/ yield return
, goto
,if(false)
等,如评论中所述。但是所有这些语句/表达式都必须由您自己在包含您的try
语句的方法中编写,因此您不必担心它们。
但是,即使除此之外,还有一种方法可以在不抛出异常或返回(或运行这两种方法中的任何一种)的情况下退出。那就是......抛出一些不是例外的东西。
C# 语言规范规定,您可以抛出的唯一内容是 class 的实例Exception
或null
文字(在这种情况下NullReferenceException
抛出 a。)见 §8.9.5:
[throw] 表达式必须表示类类型 System.Exception、派生自 System.Exception 的类类型或具有 System.Exception(或其子类)作为其有效基类的类型参数类型的值。如果表达式的评估产生 null,则会引发 System.NullReferenceException。
但是,此限制仅限制 C# 代码。C#代码编译成中间语言,不受此限制。也可在 C# 语言规范 §8.10 中找到:
某些编程语言可能支持无法表示为派生自 System.Exception 的对象的异常,尽管 C# 代码永远不会生成此类异常。
为了捕获这些异常,您需要使用通用的 catch 子句,如下所示:
try
{
//...
Foo();
}
catch
{
Bar();
}
注意:此方法仅适用于编译到 2.0 版之前的 .NET 框架。从该版本开始,CLR 将抛出的对象包装在RuntimeWrappedException
. 谢谢,斯维克!
此外,其他一些人提到杀死进程或抛出一个StackOverflowException
,这两者都可以很好地完成这项任务。除了这些可能还有其他方法,但我不这么认为(除了突然拔掉电脑,天堂禁止。)希望这有帮助!——布兰登
假设我们有以下代码:
try
{
/*Breaking statement goes here*/
Foo();
}
catch (Exception ex)
{
Bar();
}
finally
{
Baz();
}
我会将断路器分为 3 个常见原因:
代码流语句:
1.1。return
: 富(-); 酒吧(-); 巴兹(+);
1.2. goto
: 富(-); 酒吧(-); 巴兹(+);
1.3. if(false)
: 富(-); 酒吧(-); 巴兹(+);
1.4. while(true){}
: 富(-); 酒吧(-); 巴兹(-);
1.5。yield return
, 如果方法返回 IEnumerable 并yield return
出现在try
块之前: Foo(-); 酒吧(-); 巴兹(-);
1.6. yield break
, 如果方法返回 IEnumerable: Foo(-); 酒吧(-); 巴兹(-);
1.7. break
, 如果代码被循环包裹: Foo(-); 酒吧(-); 巴兹(+);
1.8. continue
, 如果代码被循环包裹: Foo(-); 酒吧(-); 巴兹(+);
进程/域/线程终止。
2.1。Process.GetCurrentProcess().Kill()
: 富(-); 酒吧(-); 巴兹(-);
2.2. Environment.Exit(0)
: 富(-); 酒吧(-); 巴兹(-);
2.3. Environment.FailFast("")
: 富(-); 酒吧(-); 巴兹(-);
2.4. AppDomain.Unload(AppDomain.CurrentDomain)
: 富(-); 酒吧(+);巴兹(+);
2.5. Thread.CurrentThread.Abort()
: 富(-); 酒吧(+);巴兹(+);
未处理的异常。
3.1。.NET 2.0 之前的非托管代码中的异常:Foo(-); 酒吧(-); 巴兹(+);
3.2. 自 .NET 2.0 以来的非托管代码中的异常:Foo(-); 酒吧(+);巴兹(+);
3.3. 自 .NET 4.0 以来损坏的进程状态异常(也未<legacyCorruptedStateExceptionsPolicy>
指定HandleProcessCorruptedStateExceptionsAttribute
):Foo(-); 酒吧(-); 巴兹(+);
3.4. .NET 4.0 之前的损坏的进程状态异常<legacyCorruptedStateExceptionsPolicy>
或HandleProcessCorruptedStateExceptionsAttribute
指定:Foo(-); 酒吧(+);巴兹(+);
3.5. 自 .NET 2.0 以来在另一个线程中出现异常并且<legacyUnhandledExceptionPolicy>
未启用:Foo(-); 酒吧(-); 巴兹(-);
3.6. .NET 2.0 之前的另一个线程中的异常或<legacyUnhandledExceptionPolicy>
已启用:Foo(+); 酒吧(-); 巴兹(+);
还有其他几个选项(当一家公司认为交易捕获了一切时,The Daily WTF 中提到了一个),即操作系统关闭、任务被终止以及机器断电(别笑,它确实发生了) )。其中一些你可以使用 Form_Closing 事件干净地处理,例如(操作系统关闭),但有些你不能。操作系统和其他应用程序(例如,崩溃时的 VS)通过每 X 分钟保存一个临时状态来绕过这些情况。如果该状态存在,则应用程序意外终止。如果不存在这样的状态,则应用程序干净地退出并且数据被正确保存。