C # solutions for debugging errors

Source: Internet
Author: User
Tags finally block protected constructor
1. system. configuration. configurationsettings. Expired ettings "is out of date [. net2.0 ]:

"System. configuration. configurationsettings. deleettings" is out of date: "This method is obsolete, it has been replaced by system. Configuration! System. configuration. configurationmanager. deleetmanager"

Error reported:
Error prompt when system. configuration. configurationmanager. deleettings ["XXX"] is used in vs. net2005
Error 1: The namespace "system. Configuration" does not contain a type or namespace name "configurationmanager" (is the Assembly reference missing ?)

Solution:
Add ". Net --> system. Configuration" to "Reference" in the project"
Modify system. configuration. configurationsettings. configurettings to system. configuration. configurationmanager. configurettings to solve the problem. ^_^2. Understand exceptions and handling in. netMaybe from the first time we use an exception, we need to often consider such issues as when to capture the exception, when to throw the exception, and the performance of the exception. Sometimes we want to know what the exception is, what is its mechanism. This article tries to discuss these issues.

The main content includes:

Why are exceptions used? we mainly discuss the selection between exceptions and error codes.

Understanding of the concept of essential exceptions

Exception mechanism: Try, catch, and finally statement Blocks

System. Exception and other exception classes in FCL

How to create a custom exception type for a custom exception class

Correct use of exceptions some rules and conventions on abnormal use

Consider performance issues to understand the impact of exceptions on performance and give some suggestions

Unhandled exceptions in the application; how to handle unhandled exceptions in the Application

1. Why should I use exceptions?

When handling errors in a program, you can use exceptions or return values. Exception Handling has many advantages over reporting errors using return values:

Exceptions have been well integrated with object-oriented languages.

In some cases, such as constructors, Operator overloading, and attributes, developers have no choice for returned values. It is impossible to report errors by using the returned values in an object-oriented framework. In the above case, the only choice is to use methods other than the return value, such as exceptions. In this case, the best way is to report errors with exceptions everywhere. This is the most important reason for reporting errors with exceptions (Jeffery Richter ).

Exceptions enhance API consistency.

The only purpose of an exception is to report an error. The returned value has multiple purposes. Reporting an error is only one of them. Therefore, if exceptions are used, the method for reporting errors is fixed, which ensures API consistency.

It is easier to make the Code Localization of error processing, and the code of error processing can be put in a more centralized position.

There are many causes for Code failure, such as reference of null objects, out-of-bounds indexing, access to closed files, and memory depletion. Without exception handling, it is very difficult to make our code easily detect these causes and recover them from them, even if possible. At the same time, the Code for such detection must be distributed in the main logic of the program, making the coding process very difficult, and the code is hard to understand and maintain.

If exception handling is used, we do not need to write code to detect these potential faults. We simply code it with confidence and think that the code is okay. This process will naturally become simple, and the code will be easy to understand and maintain. Finally, place the exception recovery code in a centralized position (behind the try code block, or higher-level call stack). When the program fails, the recovery code will be executed.

When an exception occurs, we can place the resource cleanup code in a fixed position and ensure that the code is executed.

After the resource cleaning code is moved from the main logic of the application to a fixed position, the application will become easier to write, understand, and maintain.

Easy to locate and fix bugs in the code

Once the program encounters a problem, the CLR traverses the call stack of the thread to find the code that can handle the exception. If such Code cannot be found, we will receive an "unprocessed exception" notification that developers are reluctant to see. Based on this notification, you can easily locate the problem, identify the cause, and fix the bug.

Error Codes are easy to ignore and are usually ignored. The exception is not the case.

An exception allows you to define a handler for an unhandled exception. What is the error code?

In addition, exceptions help to interact with some tools.

Various tools (such as debuggers, performance analyzers, and performance counters) always pay attention to exceptions. Returning error codes does not have these benefits.

After reading these comparisons, do you still choose error codes?

2. essence of exceptions

An exception is essentially a violation of implicit assumptions on program interfaces.

When designing a type, we should first consider the various scenarios where this type is applied. The type name is usually a noun, such as filestream and stringbuilder. Then define attributes, methods, events, and other Members for the type. The member's definition method (attribute data type, method parameters, return values, etc.) is a type of program interface. At the same time, these Members describe the operations that can be performed by the type (or its instance). Their names are usually verbs, such as read, write, flush, append, insert, and remove.

If a member of the type cannot complete its tasks, an exception should be thrown. An exception means that the type member cannot complete the function described by its name.

The Program Interface we define usually has some implicit assumptions, such as system. io. file. opentext (string path) method, which is used to open an existing UTF-8 encoded text file for reading, to complete this function, the path parameter must be a valid path, the specified file exists, and have sufficient permissions. All these requirements are recorded in the msdn document. When calling this method, we can view the document in detail and call it in the most efficient way. But we all know that this is not realistic. We are unlikely to understand all of these implicit assumptions, which inevitably violates them.

So how do developers of the opentext method notify the program that calls it and the implicit assumption is violated? The answer is to throw an exception (You may think of the return value. For details about the return value and exception trade-off, see section 1st ).

Therefore, when designing a type, we should first assume the most common usage method of the type, and then design its interface so that it can handle this situation well. Finally, consider the implicit assumptions brought about by the interface, and throw an exception when any assumptions are violated.

In this way, it is clear whether some opinions are correct or not.

Let's focus on the opentext method mentioned above to see the following two misunderstandings about exceptions.

Exceptions are related to the frequency of events.

The developer of opentext method decides when to throw an exception, but the code is called when the exception is thrown. How can the developer of opentext method know the frequency of exceptions caused by calling code?

An exception is an error.

Errors mean that the programmer has made a mistake. When the calling code mistakenly calls the opentext method in the application, how do developers who design this method know? Only the calling program can judge whether the call result is incorrect. In other words, exceptions are a kind of feedback from the opentext method on the calling program. Whether the calling result is an error is determined by the calling program and is related to the context environment of the calling program.

3. Abnormal Mechanism

The following C # Code demonstrates the standard usage of exception handling. It describes the general usage of exception handling. After the code, we have discussed in detail the try, catch, and finally statement blocks.

Try
{
// Compile the code that requires recovery or cleanup.
}
Catch (nullreferenceexception)
{
// Write code that can be restored from nullreferenceexception (or its derived type exception) here
}
Catch (exception)
{
// Compile the code in this block that can be restored from any CLS-compatible exceptions.

// In addition, it should usually be thrown again
Throw;
}
Catch
{
// We can compile the code in this block to recover from any CLS-compatible or incompatible exceptions.

// At this time, it should usually be thrown again
Throw;
}
Finally
{
// In the Finally block, we add the code to clean up the operations started in the try block.
// No matter whether an exception is thrown or not, the code is always executed here.
}

3.1 try Block

The try block usually contains operations that require cleaning or/and exception recovery. All resource cleanup code should be placed in a Finally block (to ensure that it is always executed ). The try block can also contain code that may throw an exception. The code for exception recovery should be placed in one or more catch blocks. A try block must have at least one catch block or finally block associated with it. It is meaningless to separate a try block (C # compiler does not allow you to do this ).

3.2 Catch Block

The Catch Block contains the code to be executed when an exception occurs. A try block can have 0 or more catch blocks associated with it.

If the code in the try block does not throw an exception, the CLR will not execute the Catch Block Code associated with the try block. Instead, all catch blocks are skipped, and the code in the Finally block (if any) is directly executed, and then the statement after the Finally block is executed.

The expression after the catch keyword is called the exception filter ). It indicates an exception that developers predict and can recover from. When code is executed, the catch block is searched from top to bottom. Therefore, you need to place more specific exceptions (that is, the level of the type in the inheritance system) on it. In fact, the C # compiler does not allow more specific catch blocks to appear closer to the bottom of the Code.

If the code in the try block (or the method called by the try block) throws an exception, the CLR searches for catch blocks that can identify the exception in those filters. If none of the filters associated with the try block can accept the exception, the CLR searches for a filter that can accept the exception along the call stack, if no catch block is found at the top of the stack to handle the exception, the so-called unprocessed exception will occur.

Once the CLR finds a filter that can handle the thrown exception, it will start from the try block that throws the exception, all finally blocks within the range of catch blocks matching exceptions (note that you should understand them in the call stack, the Code executed here does not include the Finally block associated with the catch block that matches the exception), calls the code that matches the Catch Block, and finally matches the Finally block associated with the Catch Block.

In C #, an exception variable can be specified in the exception filter. When an exception is caught, the variable points to the thrown object whose type inherits from system. exception. In this case, you can obtain the exception information (such as the stack trace) through this variable ). Although this object can be changed, it should not be used as a read-only variable.

The code in the Catch Block generally performs operations to recover from exceptions. At the end of the Catch Block (for example, after the Restoration Operation), we have three options:

<! -- [If! Supportlists] --> <! -- [Endif] --> throw the caught exception and notify the code in the call stack at a higher level of the exception.

<! -- [If! Supportlists] --> <! -- [Endif] --> throws a different exception to provide more information to the Code in the call stack at a higher level.

<! -- [If! Supportlists] --> let the thread exit from the bottom of the Catch Block.
If we select the first two methods, an exception will be thrown, and the CLR behavior will be the same as when dealing with the previous exception, traverse the call stack to search for the appropriate filter. If the third method is used, the exception is swallowed up, and the call stack at a higher level will not be aware of the exception. After the code in the catch block is executed, immediately execute the Finally block associated with it (if any), and then execute the code after the current try/catch/finally statement block.

The selection of these three methods will be discussed later.

3.3 Finally Blocks

The finally block contains the code to be executed. Generally, the code in the Finally block executes some resource cleanup operations, which are usually required by the actions in the try block. For example, if we open a file in the try block, we should put the code for closing the file in the corresponding Finally block.

Filestream FS = NULL;
Try
{
FS = new filestream (filename, filemode. Open );
}
Catch (overflowexception)
{
// Recovery code
}
Finally
{
If (FS! = NULL)
{
FS. Close ();
}
}

The code for clearing resources cannot be placed after the Finally block. If an exception occurs but the Catch Block fails to be captured, the code will not be executed.

Try blocks do not always require finally blocks. Sometimes try block operations do not require any cleaning.

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. Exception and other exception classes in FCL

4.1 system. Exception type.

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-compatible programming languages must 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 allow code to throw exceptions compatible with CLR.

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
Name of the Assembly that generates an exception

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 exception class structure in FCL

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

Microsoft initially thought like this: system. exception should be the base type of all exceptions, and the other two types are system. systemexception and system. applicationexception is the only method directly inherited from system. exception type. 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 directly inherit from exception (isolatedstorageexception), while some CLR throws exceptions inherit from applicationexception (such as targetinvocationexception ), in addition, exceptions thrown by some applications are inherited from systemexception (such as formatexception ). This is a bit confusing, and the result is that the existence of the systemexception and applicationexception types has little value.

5. custom exception classes

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:

<! -- [If! Supportlists] --> <! -- [Endif] --> 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.
<! -- [If! Supportlists] --> A public constructor with a string parameter creates an exception-type instance. The exception message is set to the text specified by the parameter.
<! -- [If! Supportlists] --> Public constructor with string and exception parameters, create an exception type instance, and set its message text and internal exceptions. When an exception is encapsulated, the constructor shows its importance.
<! -- [If! Supportlists] --> <! -- [Endif] --> the protected constructor with serializationinfo and streamingcontext parameters deserializes the 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. We should also understand that if you 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) returns the value of these fields.

All exception types (inherited from the exception type) should be serializable. Only in this way can an exception object be blocked when it crosses the application domain ), it can also be persisted to logs or databases. To serialize a custom exception type, first apply the serializable attribute for the type. If a new field is defined for the type, we must also implement the getobjectdata method of the iserilizable interface and the protected constructors 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. Incorrect Use

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.

For more information, see 《.. net design specifications. These specifications and suggestions in this section are usually organized by the words to be considered, avoided, or not, each article 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 must always be followed (but in special cases, they may need to be violated ).

"Think ......" It describes the rules that should be followed in general cases. 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 ......" It describes some rules that should never be violated.

"Avoid ......" It is not so absolute. It describes the situations that are generally not good but some known violations.

6.1 throw an exception.

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

× Do not return error codes.

The benefits of exceptions have been discussed in the previous section 1st, so exceptions are the main method to report errors. 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.

√ Report 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.

√ Consider terminating the process by calling system. environment. failfast (New in. NET 2.0) instead of throwing an exception. If the code encounters a serious problem, it cannot be safely executed.

× Do not use exceptions in the normal control flow. If you can avoid exceptions.

√ Consider the impact of throwing an exception on performance. For details, see section 7th.

√ To write a document for all exceptions, exceptions are essentially a violation of the implied assumptions of program interfaces. We obviously need to provide detailed documents on these assumptions to reduce the chance of exceptions caused by user code.

× Do not allow 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.

* Do not use exceptions as return values or output parameters of public members.

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

× Avoid explicitly throwing exceptions from the finally code block.

√ Prioritize the use of existing exceptions in the system namespace, rather than creating new exceptions by yourself.

√ Use 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.

× Do not create and use new exceptions only to own your own exceptions.

√ Use the 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.

√ Rich and meaningful error messages should be provided when an exception is thrown.

It should be noted that the information is provided to other developers or end users. Therefore, the information should be designed based on Oriented objects.

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

√ Make 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?

× Avoid using question marks and exclamation points in abnormal 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.

× Do not disclose security information in the exception message without permission.

√ Localized the exception information thrown by the component if you want the component to be used by developers who do not need (natural) languages.

6.2 handling exceptions

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 capture an exception of a specific type and fully understand what it means to continue executing the Catch Block, we say this situation is to process the exception.

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 case, the exception is swallowed up.

× Do not capture uncertain exceptions (such as system) in the code of the Framework (a program used by developers. exception, system. systemexception), swallowed up the exception.

× Avoid swallowing errors when capturing uncertain exceptions (such as system. Exception and system. systemexception) in application code.

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.

× Do not exclude any special exceptions from the catch code block written to transfer exceptions.

√ Capture specific types of exceptions. If you understand the causes of exceptions and make appropriate responses to errors.

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

× Do not capture exceptions that should not be caught. 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.

√ Try-finally should be used for cleaning to avoid try-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.

√ Use an empty throw statement to capture and throw an exception again. 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.

× Do not use catch blocks without parameters to handle exceptions that are not compatible with Cls (not exceptions inherited from system. 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.

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

× Avoid capturing and encapsulating exceptions with unknown types.

√ You must specify an internal exception when encapsulating an exception ).

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

6.3 use of standard exception types

× Do not throw exceptions of the exception or systemexception type.

× Do not catch exceptions of the exception or systemexception type in the framework (for use by other developers) Code unless you plan to throw them again.

× Avoid exceptions of the exception or systemexception type, unless they are in the exception processor program at the top layer.

× Do not throw an applicationexception type exception or derive a new class from it (see section 4.2 ).

√ To throw an invalidoperationexception type exception if the object is in an incorrect state.

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

√ To throw argumentexception or its subclass, if the input is invalid. Be sure to use the type at the end of the inheritance level as much as possible.

√ Set the paramname attribute when throwing argumentexception or its subclasses.

This attribute indicates which parameter causes an exception.

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

√ Use value as the name of the implicit value parameter in the attribute setting method.

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

× Do not let public APIs throw 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.

7. Performance 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-doer Mode

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.

√ Use the test-doer mode in the method to avoid performance problems caused by exceptions, if this method is used in common scenarios, it may throw an exception (the frequency of exceptions is high ).

The premise is that the "test" operation is far faster than the "do" operation. In addition, it is dangerous to access an object through multiple threads.

7.2 try-Parse Mode

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.

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

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.