Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: Design C#4.0
Hi,
 
This seems like a dumb question I should know the answer to but in the following code:
 
MyType x = new MyType();
 
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
Posted 20-Mar-13 9:30am
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

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
 
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
}
 
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".
 
[EDIT: the end of the previous and the next paragraphs have been modified, driven by the comment by Matt T Heffron.]
 
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
  Permalink  
v8
Comments
Matt T Heffron at 20-Mar-13 15:08pm
   
I would disagree with "Ideally, all exceptions should be caught only on the very top of the stack of the stack of each thread."
The exception(s) should be caught at the point in the calling hierarchy where the exceptional behavior is best addressed: by reporting/logging and/or correcting the condition.
Sometimes that is right at the call of the method throwing the exception.
For example, in a recent application I needed to scan a directory for folders which had localized resources and were named for the language/culture name. (E.g., "en", "jp", "zh-Hans"...) The .NET framework (CultureInfo class) has no function to verify that a string is a valid culture name, so I could not verify the name before attempting to create a CultureInfo object for that name. My only option was to wrap the call to CultureInfo.GetCultureInfo(name) in a try/catch; and ignore the CultureNotFoundException which would occur when the name of a directory that was NOT one of the resource directories was encountered.
 
Thus, my 4.
Sergey Alexandrovich Kryukov at 20-Mar-13 15:34pm
   
Of course, you are right!
 
My statement was "too quick", and due to this fact, oversimplified and, in fact, inaccurate. Also, the main point was the attempt to help to overcome a very bad trend to handle exceptions very locally, which defeats the purpose and lowers down the technique almost to the hell of "error status" approach.
 
Thank you for your note. I'll improve my answer soon, and of course will credit you for this help.
—SA
Sergey Alexandrovich Kryukov at 20-Mar-13 15:51pm
   
I use my own term for your idea of "where the exceptional behavior is best addressed"; I call it "competency point". The detail explanation of this approach need a couple of good code samples, I think it would go a bit beyond of the present question.
 
Please take a look: I think I fixed my inaccuracy and added some more advice. I would be interested if you share your opinion...
 
Thank you,
—SA
Matt T Heffron at 20-Mar-13 16:00pm
   
Better, up to 5.
Sergey Alexandrovich Kryukov at 20-Mar-13 16:04pm
   
That wasn't my purpose, of course; and I would be grateful for more criticism, but thank you very much.
—AS
Matt T Heffron at 20-Mar-13 16:11pm
   
Well...I'm supposed to be doing on-the-job "real work" :) I didn't look at your references.
 
This:
 
"Ideally, most exceptions are called rarely, typically pretty far away from the point where they are thrown."
 
is a little confusing. Did you mean "...are CAUGHT rarely,..."? Although, that wouldn't read quite sensibly either.
Sergey Alexandrovich Kryukov at 20-Mar-13 16:46pm
   
Of course. I'll improve it...
Should better be "ideally... caught in a very few points"...
Thank you.
—SA
Monjurul Habib at 20-Mar-13 15:14pm
   
5++
Sergey Alexandrovich Kryukov at 20-Mar-13 15:35pm
   
Thank you, Monjurul.
—SA
Patrick Skelton at 20-Mar-13 15:16pm
   
Extremely clear and informative! Thank you very much.
 
I kind-of knew all what you said, but it had become a bit fuzzified in my brain because I haven't done any real programming for a while. Nice and clear now. :-)
Sergey Alexandrovich Kryukov at 20-Mar-13 15:35pm
   
Thank you for your nice words, Patrick.
—SA
Maciej Los at 7-Jun-13 12:11pm
   
+5!
Sergey Alexandrovich Kryukov at 7-Jun-13 14:19pm
   
Thank you, Maciej.
—SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

If the constructor throws an exception, the assignment doesn't happen because the execution continues where the exception is caught.
  Permalink  
Comments
Sergey Alexandrovich Kryukov at 20-Mar-13 15:37pm
   
This is correct, but for those who did not understand it in first place, it really needs explanation. What is "execution continues"? This time, I voted 4, too. :)
And now I'm going to improve my own answer; again, thank you for your useful comment.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 6,569
1 Sergey Alexandrovich Kryukov 6,168
2 DamithSL 5,228
3 Manas Bhardwaj 4,717
4 Maciej Los 4,150


Advertise | Privacy | Mobile
Web01 | 2.8.1411022.1 | Last Updated 7 Jun 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100