Understanding exceptions in. Net (2)

Source: Internet
Author: User
Tags protected constructor

The previous article discussed the advantages of exceptions, the nature of exceptions, and the mechanism of exceptions.
Here we will discuss pre-defined exception classes in FCL, custom exception classes, correct usage exceptions (throws, captures, and encapsulates), and finally provide performance suggestions.

4, System. ExceptionAnd other FCLException class in

4.1 system. ExceptionType

CLR allows us to throw an instance of any type -- int32, String, etc. -- as an exception. However, Microsoft actually defines the system. Exception type and specifies that all Cls-compatibleProgramming LanguageMust be able to throw and capture the exception types inherited from system. Exception. The exception type inherited from system. Exception is considered to be CLS compatible. C # and many other languages only allowCodeThrow a CLR-compatible exception.

The system. Exception type is a simple type. The following table lists some of its attributes.

Attribute

Access permission

Type

Description

Message

Read-Only

String

Contains an auxiliary text to describe the cause of the exception. When an unhandled exception occurs, the information is usually written to the log. This information is usually invisible to users, so you should try to use technical words to help other developers correct the code.

Data

Read-Only

Idictionary

A reference to a set of key-value pairs. Generally, information should be added to the set before an exception is thrown, and the code that captures the exception uses the information for exception recovery.

Source

Read/write

String

ExceptionProgramSet Name

Stacktrace

Read-Only

String

Contains the name and signature of the method that throws an exception in the call stack. This property is of great value for debugging.

Targetsite

Read-Only

Methodbase

Throw an exception.

Helplink

Read/write

String

Gets or sets the link to the abnormal associated help file.

Innerspontoin

Read-Only

Exception

If the current exception is generated when processing another exception, this attribute indicates the previous attribute. This attribute is usually null. The exception type also provides a public method getbaseexception to traverse the linked list composed of internal exceptions and return the first exception.

4.2 FCLAbnormal class structure in

The. NET Framework class library (FCL) defines many exception types (which ultimately inherit from the exception class ).

MicrosoftInitial ideaYes: system. exception should be the base type of all exceptions. The other two types: system. systemexception and system. applicationexception are the only exception types directly inherited from system. Exception. In addition, all exceptions thrown by CLR are inherited from systemexception, and the exceptions thrown by the application must be inherited from applicationexception. In this way, developers can write catch blocks to catch exceptions thrown by all CLR or exceptions thrown by all applications.

Unfortunately, FCL does not follow this principle well. Some exception classes are directly inherited from exception (Isolatedstorageexception), Some CLR throws exceptions are inherited from applicationexception (for exampleTargetinvocationexception), And some applications throw exceptions that inherit from systemexception (for exampleFormatexception). This is a bit confusing, and the result is that the existence of the systemexception and applicationexception types has little value.

5, Custom exception class

If FCL does not define an appropriate exception type for us, we should consider creating our own exception classes.

In general, the custom exception class should inherit from the exception type or other base types similar to the exception. If the defined type is not intended to be the base type of other types, it should be identified as sealed.

The exception base type defines four constructors:

    • A public no-argument (default) constructor creates an instance of the exception type and sets the values of all fields and attributes to the default value.
    • A public constructor with a string parameter creates an instance of the exception type. The message of the exception is set to the text specified by the parameter.
    • A public constructor with string and exception parameters creates an exception type instance and sets its message text and internal exceptions.When an exception is encapsulated, the constructor shows its importance..
    • A protected constructor with serializationinfo and streamingcontext parameters deserializes an exception object instance. Remember, if the exception type is sealed, the method should be declared as private, so that the constructor can call the same constructor of the base type, in this way, the fields of the base class can be correctly serialized.

When defining our own exception types, we should implement these four constructors, and they all need to call the corresponding constructors in the base type.

Of course, the defined exception type inherits all fields and attributes of the exception type. In addition, we can add our own fields and attributes for it. For example, a virtual (virtual) string attribute paramname is added to system. argumentexception (all other attributes are inherited from the exception type ). Argumentexception also defines two new Constructors (except the preceding four) to initialize the paramname attribute. Here we should also understand,To add fields for the exception type, make sure to add the necessary constructor to initialize these fields, and define the corresponding attributes or other members (such as methods) to return the values of these fields..

All exception types (inherited from exceptionType) should be serializable.Only in this way can an exception object be blocked when it spans the application domain, and can be persisted to logs or databases. To serialize a custom exception type, first apply the exception typeSerializableAttribute; if the type defines a new field, we must also make it implement the iserilizable InterfaceGetobjectdataMethod and the protected constructor mentioned above.

The following example demonstrates how to correctly create a custom exception type:

To implement the above four constructors, we recommend using code snippet in VS 2005:

After you press the tab twice, Vs will generate the basic structure of the class for you :). We will write code on this basis.
The complete code of the class is as follows:

// Serializable for class applications
[Serializable]
Public sealed class customexception: exception
{
// Added custom Fields
Private string stringinfo;
Private bool booleaninfo;
// Implement three public constructors. Here, the constructors of the base class are simply called.
Public customexception (){}
Public customexception (string message): Base (Message ){}
Public customexception (string message, exception inner)
: Base (message, inner ){}
// Deserialization constructor required to implement the iserialization interface.
// Because this class is sealed, the constructor is private.
Private customexception (serializationinfo, streamingcontext context)
: Base (Info, context)
{
Stringinfo = info. getstring ("stringinfo ");
Booleaninfo = info. getboolean ("booleaninfo ");
}
// Add a constructor to ensure that the custom fields are correctly initialized.
Public customexception (string message, string stringinfo, bool booleaninfo)
: Base (Message)
{
This. stringinfo = stringinfo;
This. booleaninfo = booleaninfo;
}
Public customexception (string message, exception inner, string stringinfo, bool booleaninfo)
: Base (message, inner)
{
This. stringinfo = stringinfo;
This. booleaninfo = booleaninfo;
}
// Access custom fields through attributes or other members
Public String stringinfo
{
Get {return stringinfo ;}
}
Public bool booleaninfo
{
Get {return booleaninfo ;}
}
// Override the getobjectdata method.
// If a custom field is added, you must override the implementation of the getobjectdata method of the base class.
Public override void getobjectdata (serializationinfo info, streamingcontext context)
{
// Serialize custom data members
Info. addvalue ("stringinfo", stringinfo );
Info. addvalue ("booleaninfo", booleaninfo );
// Call the base class method to serialize its members
Base. getobjectdata (Info, context );
}
Public override string message
{
Get
{
String message = base. message;
If (stringinfo! = NULL)
{
Message + = environment. newline +
Stringinfo + "=" + booleaninfo;
}
Return message;
}
}
}

Use the following code to test the serialization of exceptions:

// Create a customexception object and serialize it
Customexception E = new customexception ("new custom exception", "my string Info", true );
Filestream FS = new filestream (@ "test", filemode. Create );
Iformatter F = new soapformatter ();
F. serialize (FS, e );
FS. Close ();
// Deserialize the customexception object and view its fields
FS = new filestream (@ "test", filemode. Open );
E = (F. deserialize (FS) as customexception;
FS. Close ();
Console. writeline (E. Message );

System. runtime. serialization. formatters. Soap. dll must be referenced here.

6, Correct use exception

According to the discussion in section 2nd, we have learned what kind of situation can be called exceptions. The following are some rules or suggestions for abnormal use.

These specifications and suggestions in this section are usually describedYes, consider, avoid, or notThese words are organized, each of which describes a good or bad practice. For good practices, √ is used. For some bad practices, × is used. Different wording can also reveal the importance of this specification.

"Yes ......"Describes the rules that always follow (but in special cases, they may need to be violated ).

"Consider ......It describes the rules that should be followed in general cases. But if you fully understand the principles behind the rules and have good reasons not to follow them, do not fear breaking the rules.

"Don't ......"Describes someAlmost never violate.

"Avoid ......"Is not so absolute, it describes the situations that are generally not good, but there are some known violations.

6.1Throw an exception

When designing our own methods, we should consider how to correctly throw exceptions.

×NoReturns an error code.

The advantages of exceptions have been discussed in the previous section 1st. Therefore, exceptions are reported as errors.Main Method. Remember that each exception has two types of information: one is the message attribute, and the other is the exception type. The exception handler determines what operations should be performed based on it.

YesReport operation failure by throwing an exception.

If a method fails to complete the task it should complete, it should be considered as a method-level operation failure and an exception is thrown.

ConsiderationsBy callingSystem. environment. failfast(Newly in. NET 2.0) To terminate the process, instead of throwing an exception. If the code encounters a serious problemUnable to proceed safely.

×NoAn exception is used in a normal control flow, if it can be avoided.

ConsiderationsThrows an exception and may affect the performance. For details, see section7Section.

YesWrite a document for all exceptions,Exceptions are essentiallyA violation of implicit assumptions on program Interfaces.We obviously need to provide detailed documents on these assumptions to reduce the chance of exceptions caused by user code.

×NoAllow public members to decide whether to throw an exception based on a certain option.

For example:

// Poor design
Public type GetType (string path, bool throwonerror)

The caller is more difficult than the method designer to decide whether to throw an exception.

×NoUse an exception as the return value or output parameter of a Public member.

In this way, the benefits of reporting failed operations with exceptions will be lost.

×AvoidExplicitlyFinallyCode block throws an exception.

ConsiderationsPrioritySystemThe existing exceptions in the namespace, rather than creating new exceptions by yourself.

YesUse a custom exception type. If the error handling method is different from other existing exception types.

For details about how to create a custom exception class, see section 5th.

×NoCreate and use new exceptions only to own their own exceptions.

YesThe most reasonable and targeted exceptions.

It is always wrong to throw a system. Exception. If you do so, think about whether you really understand the cause of the exception.

YesRich and meaningful error messages are provided when an exception is thrown.

Note that the information is provided to other developers or end users.This information should be designed according to the object-oriented.

YesMake sure that the syntax of the exception message is correct (natural language, such as Chinese and English ).

YesMake sure that each sentence in the exception message has a full stop.

This seems to be too detailed, so think about this situation: When we use the message information of the FCL predefined exception, have we put an end to it. If the information we provide does not have a full stop, will it be added when other developers use it?

×AvoidUse question marks and exclamation points in exception messages.

Maybe we are used to using exclamation marks to "Warn" some operations have problems. ask ourselves what it feels like if the code we use returns an exclamation mark.

×NoThe Security Information is leaked in the exception message without permission.

ConsiderationsLocalized the exception information thrown by the component. If you want the component to be used by developers who do not use (natural) languages.

6.2Exception Handling

According to the discussion in section 6.1, we can decide when to throw an exception, select a suitable type for it, and design reasonable information. The next step is how to handle the exception.

If a Catch Block is used to catch exceptions of a specific typeWhat does continued execution mean to the application?In this case, the exception is handled.

If the specific type of the captured exception is unknown (usually this is the case) and the Application continues to be executed without fully understanding the cause of the operation failure or responding to the operation failure, in this caseSwallowed the exception.

×NoIn the code of the framework (the program that is used by developers), when exceptions of specific types are captured (suchSystem. Exception,System. systemexception), Swallowed up the exception.

×AvoidIn the application code, exceptions with unknown types are captured (for exampleSystem. Exception,System. systemexception), Swallowed up the error.

Sometimes it is acceptable to swallow exceptions in an application, but you must be aware of the risks.. Exceptions usually result in inconsistent States. If you rashly swallow the exceptions and let the program continue to run, the consequences will be unimaginable.

×NoWritten in order to transfer exceptionsCatchCode block to exclude any special exceptions.

ConsiderationsCapture exceptions of a specific type, ifUnderstanding the causes of exceptions,And make appropriate responses to errors.

At this time, you must be sure that,The program can be completely recovered from the exception.

×NoCapture exceptions that should not be captured. Generally, exceptions should be passed up the call stack.

This is extremely important. If exceptions that are not captured are captured, the bug is more difficult to detect. All Bugs should be exposed during development and testing.

YesUsed for cleanupTry-finallyTo avoid usingTry-catch.

For well-written code, try-finally is more frequently used than try-catch. This may be contrary to intuition, because sometimes we may think: isn't a try a catch? We need to know that, on the one hand, we need to consider the consistency of the program status, and on the other hand, we need to consider the cleaning of resources.

YesUse null when capturing and re-throwing an exceptionThrowStatement. This is the best way to keep the call stack.

If a new exception is thrown after an exception is caught, the reported exception is no longer an actual exception. Obviously, this is not conducive to program debugging. Therefore, the original exception should be thrown again.

×NoUseCatchBlock to process not matchCLSCompatible exceptions (not inherited fromSystem. Exception).

Sometimes it doesn't make sense to pass the exception thrown by the underlying code to the high-level. At this time, you can consider encapsulating the underlying exception to make it meaningful to the high-level users. In another case, it is more important to know that the Code throws an exception, and the type of the exception does not matter. In this case, exceptions can be encapsulated.

ConsiderationsEncapsulate the exceptions thrown at a lower level if the exceptions at a lower level are meaningless in a higher stage.

×AvoidCapture and encapsulate exceptions with unknown types.

YesSpecify an internal exception when encapsulating an exception (Inner exception).

This is extremely important and will be helpful for code debugging.

6.3Use of standard exception types

×NoThrowExceptionOrSystemexceptionType exception.

×NoCaptured in the framework (for use by other developers) CodeExceptionOrSystemexceptionType exception, unless you want to throw it again.

×AvoidCaptureExceptionOrSystemexceptionType exception, unless it is in the top-level exception processor program.

×NoThrowApplicationexceptionType exception or derive a new class from it (see4.2Description ).

YesThrowInvalidoperationexception type exception, if the object is in an incorrect state.

One example is to write data to a read-only filestream.

YesThrow argumentexceptionOr its subclass. If the input parameter is invalid. Be sure to use the type at the end of the inheritance level as much as possible.

YesWhen argumentexception is thrownOr set paramname for its subclasses.Attribute.

This attribute indicates which parameter causes an exception.

Public static fileattributes getattributes (string path)
{
If (Path = NULL)
{
Throw new argumentnullexception ("path ",);
}
}

YesIn the attribute setting methodValueName of an implicit value parameter.

Public fileattributes attributes
{
Set
{
If (value = NULL)
{
Throw new argumentnullexception ("value ",);
}
}
}

×NoMake publicAPIThrow these exceptions.

If these exceptions are thrown, implementation details are exposed, and the details may change over time.

In addition, do not explicitly throw stackoverflowexception, outofmemeryexception, comexception, and sehexception. Only CLR can throw these exceptions.

7Performance Considerations

We often have performance concerns when using exceptions, especially when debugging. Such concerns are reasonable. When a member throws an exception, the impact on performance is exponential. When we follow the previous specifications, we may still achieve good performance. Two modes are recommended in this section.

7.1 tester-doerMode

Sometimes, we can break down a member that throws an exception into two members to improve the performance of the member. Next let's take a look at the Add method of the icollection <t> interface.

Icollection <int> numbers =...
Numbers. Add (1 );

If the set is read-only, the add method throws an exception. In scenarios where the add method often fails, this may cause performance problems. One way to mitigate the problem is to check whether the set is writable before calling the add method.

Icollection <int> numbers =...
...
If (! Numbers. isreadonly)
{
Numbers. Add (1 );
}

The member used for testing the condition becomes the tester. Here is the isreadonly attribute. The member used to perform the actual operation and may throw an exception to become the doer. Here is the add method.

ConsiderationsUse in MethodTest-doerMode to avoid performance problems caused by exceptions. If this method is used in common scenarios, an exception may be thrown (the exception frequency is high ).

Premise:"Test"The operation is far greater than "do"Fast operation. In addition, it is dangerous to access an object through multiple threads.

7.2 try-ParseMode

The try-Parse mode is even faster than the tester-doer mode and should be used in APIs with extremely high performance requirements. This mode adjusts the member name so that the member's semantics contains a pre-defined number. For example, datetime defines a parse method. If the parsing string fails, it throws an exception and provides a corresponding tryparse method. If the parsing fails, false is returned, if the result is successful, an output parameter is used to return the result.

When using this mode, note that if the (method) operation fails due to reasons other than the try operation, an exception should still be thrown.

ConsiderationsUse try-Parse in the MethodModeTo avoid performance problems caused by exceptions. If this method is used in common scenarios, an exception may be thrown.

Refer:
. NET Framework programming-Jeffery Richter
. Net design specifications-Krzysztof cwalina, Brad Abrams
Visual C #2005 recipes-Allen Jones, Matthew MacDonald

author: Anders Cui
Source: http://anderslly.cnblogs.com
the copyright of this article belongs to the author and the blog Park, you are welcome to reprint, but without the author's consent must retain this paragraph statement, the connection to the original text is clearly displayed on the Article page. Otherwise, the legal liability is reserved.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.