ArticleDirectory
- Catch exceptions private or simply handle exceptions and continue to throw
- How to quickly and efficiently define your own exception types
- Exceptions and Performance
Read the Exception Handling Section in C # basic books over the past few days and summarize my achievements!
There are several gains in total:
- How can I capture all thrown exceptions (including captured and uncaptured exceptions) at the top of the app without affecting the way in which the app processes each exception?
- Are exceptions caught private or are exceptions thrown after simple handling?
- How can I quickly and efficiently define my own exception types?
- Exceptions and Performance
The following is a detailed description:
Capture applicationsProgramAll exceptions thrown in the domain
In the development process, sometimes we may need a unified interface to process all the currently hostedCodeException thrown at any location in. In fact, many exceptions have been captured by the code we write in different locations, and some code has not been captured, some exceptions are caught and thrown again. In fact, there is a very important event on the appdomain object, that is, firstchanceexception. This event can be triggered after an exception is triggered, and it is triggered first before it is captured by other code, and include the exception object in firstchanceexceptioneventargs. In other words, this event can immediately report to us any thrown exception, including re-throw. The following is its declaration:
//// Summary:// Occurs when an exception first occurs in managed code, before the runtime// Has made its first pass searching for suitable exception handlers.Public EventEventhandler <firstchanceexceptioneventargs> firstchanceexception;
As you can see from the annotations, this event allows us to taste the freshest and most timely exceptions.
The following is a demo example I wrote to observe its behavior. The first is the method for registering the firstchanceexception event in currentdomain in the main function.
Static VoidMain (String[] ARGs) {appdomain. currentdomain. firstchanceexception + =NewEventhandler <system. runtime. exceptionservices. firstchanceexceptioneventargs>
(currentdomain_firstchanceexception); simpleexceptiontest. test (); console. readline ();} static void currentdomain_firstchanceexception ( Object sender, system. runtime. predictionservices. firstchanceexceptioneventargs e) {console. writeline ( "currentdomain_firstchanceexception:" ); console. writeline (E. exception); console. writeline (); console. writeline () ;}
Then I wrote a simpleexceptiontest class that can throw exceptions and capture them myself:
Class Simpleexceptiontest { Static Void Testinner (){ Try {Console. writeline ( "Exec in try block! " ); Object O = Null ; Console. writeline (O. GetType ());} Catch (Nullreferenceexception e) {console. writeline ( "Exec in catch block! " ); Console. writeline (E. Message); console. writeline ( "Exec end Catch Block! " ); Throw ;} Finally {Console. writeline ("==================== Exec in finally block! " ); Int I = 0; // An exception occurs in the finnally block. Int J = 5/I; console. writeline ( "==================== Exec end in finally block! " );}} Public Static Void Test (){ Try {Testinner ();} Catch (Exception e) {console. writeline (E. Message );}}}
The execution result of the program is as follows:
Exec in try block!
Currentdomain_firstchanceexception: object reference not set to an instance of
Object.
Exec in catch block!
Object reference not set to an instance of an object.
Exec end Catch Block!
Currentdomain_firstchanceexception: object reference not set to an instance of
Object.
==================== Exec in finally block!
Currentdomain_firstchanceexception: attempted to divide by zero.
Attempted to divide by zero.
The preceding execution results show the following problems:
- Currentdomain_firstchanceexceptionThe exception is always caught immediately, including the rethrow exception in the Catch Block.
- When an exception is thrown in the finnally block, the execution of the Finally block is interrupted. We know that in finally blocks, some cleanup code is usually written, such as releasing resources enabled in try and closing wait Windows started in try. So if you throw an exception in finally, the cleanup will be interrupted.
So how can we ensure that the cleaning work in the finnally block can be completed correctly? Do we need to nest a trycatchfinnally statement in the Finally block? This will form an endless loop, the last finnally is always not guaranteed. The only feasible method is to do not place redundant code in finnally, and carefully write high-quality cleaning code to pray that it will not throw exceptions.
Catch exceptions private or simply handle exceptions and continue to throw
This is also a question for beginners. I think there are several principles:
1. Just private the exception that you can clearly know how to handle. For example, from the business and project group conventions, when dividing by 0, we will return the value of this expression to 0. This is a regulation for exception handling. It can be used to private the exception, so that the exception stops here and will not be thrown to the upper layer of the call stack.
2. You are an independent module, and you have to make the decision robust, you can capture all exceptions and handle private content in accordance with regulations, if it cannot be processed, it records or reports exceptions to users or servers in a friendly manner, but the program does not crash.
3. Do not know how to handle exceptions. After capturing the exceptions, perform simple processing (for example, package the exceptions and add a clearer location for exceptions, when an exception is triggered, the Service parameter information is thrown and sent to the upper layer of the call stack for post-processing capture.
How to quickly and efficiently define your own exception types
To customize an exception, you only need to define a class and inherit from system. exception or its subclass. However, the exception types are numerous and redundant, and our team members cannot remember how many exceptions should be captured. It is also easy to define an exception that meets the business needs.
We recommend a general exception <texceptionargs> defined in CLR via C #, as long as a new texceptionargs is defined, we can get a practical custom exception type.
[Serializable] Public Sealed Class Exception <texceptionargs>: exception, iserializable Where Texceptionargs: exceptionargs { Private Const String c_args = "ARGs" ; // For (de) serialization Private Readonly Texceptionargs m_args; Public Texceptionargs ARGs {get { Return M_args ;}} Public Exception (string message = Null , Exception innerexception = Null ): This ( Null , Message, innerexception ){} Public Exception (texceptionargs ARGs, string message = Null , Exception innerexception = Null ): Base (Message, innerexception) {m_args = ARGs ;} // The constructor is for deserialization; since the class is sealed, the constructor is // Private. If this class were not sealed, this constructor shocould be protected [Securitypermission (securityaction. linkdemand, flags = securitypermissionflag. serializationformatter)] Private Exception (serializationinfo info, streamingcontext context ): Base (Info, context) {m_args = (texceptionargs) info. getvalue (c_args, Typeof (Texceptionargs ));} // The method for serialization; it's public because of the iserializable Interface [Securitypermission (securityaction. linkdemand, flags = securitypermissionflag. serializationformatter)] Public Override Void Getobjectdata (serializationinfo info, streamingcontext context) {info. addvalue (c_args, m_args ); Base . Getobjectdata (Info, context );} Public Override String message {get {string basemsg = Base . Message; Return (M_args = Null )? Basemsg: basemsg +"(" + M_args.message + ")" ;}} Public Override Boolean equals (Object OBJ) {exception <texceptionargs> Other = OBJ As Exception <texceptionargs>; If (OBJ = Null ) Return False ; Return Object. Equals (m_args, other. m_args )&& Base . Equals (OBJ );} Public Override Int Gethashcode (){ Return Base . Gethashcode () ;}} [serializable] Public Abstract Class Predictionargs { Public Virtual String message {get { Return String. Empty ;}}}}
Below I will use this generic exception class to construct my own exception types:
First, an exception parameter class is defined to calculate the distance between two cities, inherited from predictionargs.
[Serializable] Public Sealed Class Calcdistanceerrorargs: predictionargs {String M_cityid1 = String . Empty; String M_cityid2 = String . Empty; Public Calcdistanceerrorargs ( String Cityid1, String Cityid2 ){ This . M_cityid1 = cityid1; This . M_cityid2 = cityid2 ;} Public Override String Message {get { Return String . Format ( "City1 'id = '{0}', city2 'id = '{1 }'" , M_cityid1, m_cityid2 );}}}
Then write a function and throw an exception like this:
Public static void throwmyownexceptiontype () { throw New exception
(
new calcdistanceerrorargs (
"Nanjing" ,
"Beijing" ),
"the distance between the two cities cannot be obtained" ) ;}
Use the following code to capture exceptions:
Try{Throwmyownexceptiontype ();}Catch(Exception <calcdistanceerrorargs> E) {console. writeline (E );}
During running, we can view the exception as shown in:
The output exception information is as follows:
Consoleapplication1.exception' 1 [consoleapplication1.calcdistanceerrorargs]: the distance between the two cities cannot be obtained (city1 'id = 'nanjing', city2 'id = 'beijing ')
At consoleapplication1.simpleexceptiontest. throwmyownexceptiontype () in D: \ Study prj \ consoleapplication1 \ consoleapplication1 \ simpleexceptiontest. CS: line 57
At consoleapplication1.simpleexceptiontest. Test () in D: \ Study prj \ consoleapplication1 \ consoleapplication1 \ simpleexceptiontest. CS: line 47
Well, I hope this generic exception class will help you with custom exceptions.
Exceptions and Performance
In the following reply, some netizens suggested that throw will have a certain impact on the performance, and the impact must be there. I will not elaborate on it in detail. Please refer to the two articles in msdn:
Http://blogs.msdn.com/ B /kcwalina/archive/2005/03/16/396787.aspx (Design Guidelines update: exception throwing) (1.2 exceptions and performance)
Http://msdn.microsoft.com/zh-cn/library/ms229009.aspx (exceptions and performance)