C#构造函数中的异常会导致调用者分配失败吗? [英] Does Exception in C# Constructor Cause Caller Assignment to Fail?

查看:78
本文介绍了C#构造函数中的异常会导致调用者分配失败吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





这似乎是一个愚蠢的问题,我应该知道答案,但是在下面的代码中:



Hi,

This seems like a dumb question I should know the answer to but in the following code:

MyType x = new MyType();





如果构造函数抛出异常,是否会阻止分配发生?



我99%肯定答案是是 ',但我似乎无法在任何地方找到它的参考。





亲切的愿望,帕特里克



If the constructor throws an exception, does that prevent the assignment from happening?

I'm 99% sure the answer is 'Yes', but I can't seem to find a reference to it anywhere.


Kind wishes, patrick

推荐答案

也许你错过了关于异常的重要事情,而不是构造函数。异常传播高于通常的调用/返回机制基于线程堆栈,它使跳远(旧的C / C ++开发人员在英特尔CPU的实模式中可能记住这个想法)将堆栈向上移动到最近的捕获。所以,没有任何失败,创建 x 的整个上下文将从堆栈中删除(想想堆栈展开)。



通常,结构化异常处理中的整个想法都会被其他东西取代。没有错误,基本上没有错误状态。对象本身被删除。这是一种时间机器:异常传播将及时执行跳转到尚未创建 x 的上下文的那一刻。让我们比较一下:



Perhaps you are missing something important about exceptions, not constructors. Exception propagation goes "above" the usual call/return mechanism bases on the thread stack, it makes a "long jump" (old C/C++ developers in real-mode of Intel CPU might remember the idea) up the stack to the closest catch. So, not that anything failed, the whole context where x is created is removed from stack (think "stack unwinding").

Generally, the whole idea in Structured Exception Handling is replaced with something else. There are no "errors", essentially, there are no error statuses. The objects themselves are removed. This is a kind of a time machine: exception propagation jumps execution "back in time", to the moment where the context of x was not yet created. Let's compare:

MyType SomeMethod(/* ... */) {
    MyType x = new MyType(); // exception here jumps out of the SomeMethod context and maybe its caller
    // ...
    return x;
}





with





with

MyType SomeMethod(/* ... */) {
    try {
        MyType x = new MyType();
    } catch (SomeException) {}
    // ...
    return x; // won't compile, because x is not defined
}











and with

MyType SomeMethod(/* ... */) {
    MyType x;
    try {
        MyType x = new MyType();
    } catch (SomeException) {}
    // ...
    return x; // won't compile, because x is not initialized
}





,最后是





and, finally, with

MyType SomeMethod(/* ... */) {
    MyType x = null;
    try {
        MyType x = new MyType();
    } catch (SomeException) {}
    // ...
    return x; // will return null, or whatever it was before calling the constructor
}





如你所见,没有任何歧义的空间。



现在,在实践中,最好使用第一个选项,避免在本地捕获异常。你想放手。理想情况下,异常应该在极少数点捕获,通常距离它们抛出的点非常远。这种方法有助于将异常处理与正常处理隔离开来:异常应该异常处理。正如Matt T Heffron在hist重要评论(见下文)中正确指出的那样,应该抓住例外情况,以便最好地解决特殊行为问题。我称之为能力点







作为一种简约的默认异常处理方法,所有异常都应该仅在堆栈的最顶层堆栈中捕获。每个线程。面向事件的UI是一种特殊情况;你需要捕获最上层循环中的所有异常,即应用程序事件循环。完成此操作后,根据能力点方法,某些特殊情况可能会出现一些例外情况。真正应该在非常狭窄的环境中捕获所有异常的情况(如上面的示例所示)非常罕见;例如,通常需要补偿一些设计不良的API,其中源代码无法访问补丁;在开发人员完全控制的正常情况下,最好避免使用这种技术。



请查看我过去的答案:

我如何制作一个循环当滚动条到达底部时将停止 [ ^ ],

尽管存在任何未处理的异常,仍然保持ac#windows表单应用程序运行 [ ^ ],

当我运行一个应用程序时一个例外是如何处理这个? [ ^ ],

扔。 .then ... rethrowing [ ^ ],

错误记录和屏幕截图。 [ ^ ],

捕捉异常 [ ^ ],

处理类库中的异常(dll) [ ^ ],

异常详细信息:System.Runtime.InteropServices.COMException:使用CLSID {0006F03A-0000-0000-C000-000000000046}检索组件的COM类工厂由于以下错误而失败:... [ ^ ]。



-SA



As you can see, there is no a room for any ambiguity.

Now, in practice, it's the best to use the very first option and avoid catching exceptions too locally. You want to let go. Ideally, exceptions should be caught in very few points, typically pretty far away from the point where they are thrown. That approach helps to isolate exception handling from "normal" processing: exceptions should be processed exceptionally. As Matt T Heffron correctly pointed out in hist important comment (see below), the exceptions should be caught where the exceptional behavior cab be best addressed. I call it "competency point".



As a minimalistic "default" exception handling approach, all exceptions should be caught only on the very top of the stack of the stack of each thread. Event-oriented UI is a special case; you need to catch all exceptions in the uppermost loop, the application event loop. When this is done, some exceptions can be could for some special cases, according to the "competency point" approach. The cases when the all the exceptions really should be caught immediately in a very narrow context (as shown in my samples above) are pretty rare; for example, it is pretty typically needed to compensate for some poorly designed APIs with source code unreachable for a patch; in normal situations under the full control of the developers, such technique is best avoided.

Please see my past answers:
How do i make a loop that will stop when a scrollbar reaches the bottom[^],
Keep a c# windows form application running despite any unhandled exception[^],
When i run an application an exception is caught how to handle this?[^],
throw . .then ... rethrowing[^],
Error Logging and Screen Shot.[^],
Catching an Exception[^],
Handling exceptions in class library (dll)[^],
Exception Details: System.Runtime.InteropServices.COMException: Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed due to the following error:...[^].

—SA


如果构造函数抛出异常,分配不会发生,因为执行会继续捕获异常。
If the constructor throws an exception, the assignment doesn't happen because the execution continues where the exception is caught.


这篇关于C#构造函数中的异常会导致调用者分配失败吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆