Location>code7788 >text

Abnormal use

Popularity:300 ℃/2025-02-03 21:28:20

Abnormal use

Regardless of whether it is the network or publishing, there are relatively few information about C# abnormality, and there are few developers in the field of industrial control in my industrial control field. Different is actually a very good mechanism and is worth promoting. To this end, I write this article based on the accumulation of past learning and combined with some project experience.

1. Why should you use abnormalities

Before starting this article, let's take a look at the commonly used "report errors" methods:

  • Method 1: Return the error code

shortcoming:

  1. Users have to judge the return value, resulting in an increase in "circle complexity";
  2. If the method needs to be returned, the return content has to be passed through the "out" parameter.

The following is a pseudo -code. We can see that there are many inconvenience to use the error code:

Client client = new client ();
 if (() == 1)
 {{
     if String Content == 1)
     {{
         // Execute other actions
     }
 }

 class client
 {{
     Public int Connect ()
     {{
         // Execute other actions
         If (SuccessEded)
         {{
             // Successful execution, return 1
             Return 1;
         }
         else
         {{
             // The execution fails, and the error code is returned
             Return errorCode;
         }
     }

     Public int Receive (out String Result)
     {{
         If (SuccessEded)
         {{
             result = result;
             Return 1;
         }
         else
         {{
             result = null;
             Return errorCode;
         }
     }
 }
  • Method 2: Elementary information of global attribute records

shortcoming:

  1. You need to judge global attributes, users can easily miss;
  2. It will also increase the "circle complexity".
Client value = new client ();
 ();
 if (== 1)
 {{
     string content = ();
     if (== 1)
     {{
         // Execute other actions
     }
 }

 class client
 {{
     public int errorCode {get; private set;}
     public void connect ()
     {{
         // Execute other actions
         If (SuccessEded)
         {{
             // Successful execution, the global attribute is set to 1
             ErrorCode = 1;
             Return;
         }
         else
         {{
             // The execution failed, set the error code
             ErrorCode = errorcode;
             Return;
         }
     }

     Public String Receive ()
     {{
         If (SuccessEded)
         {{
             ErrorCode = 1;
             Return result;
         }
         else
         {{
             ErrorCode = errorcode;
             Return null;
         }
     }
 }

The above two mechanisms are not only cumbersome, but the return error code cannot be used in some scenarios where there is no return value:

  • Constructed function execution fails
  • Set the attribute value execution failure

And abnormalities can make up for these defects.

Info

The book "Framework Design Guide" has explained in detail the benefits of abnormal abnormalities.

  • Abnormal combination with object -oriented language is precise. In terms of constructor, computing weight load, and attributes, developers cannot choose to return the value. For this reason, for object -oriented frameworks, error reports based on the return value cannot be standardized.

  • The abnormality promotes the consistency of the API because they are only designed for error reports. In contrast, there are many uses for returning values, and the error report is just one of the subsets. For this reason, although abnormalities can be restricted in specific modes, APIs that report errors by returning value reports are likely to use a large number of modes. Win32 API is a typical example of this inconsistent: it uses BOOL, Hresults, and GetLasterror.

  • In an error report based on the return value, the error processing code is always placed near the fault point. However, for abnormal processing, the developers of the application can have their own choices. They can capture abnormalities near the fault point, or they can concentrate the error processing code on the call stack.

  • Error processing code is easier to be localized. If the code reported by the return value is very strong, it often means that there is an IF statement in almost every functional code. These IF statements are used to deal with failure. With an abnormal error report, you can usually write a strong code in this way: multiple methods or operations are performed in order, and then you can handle errors according to the group behind the TRY syntax block, and you can even deal with higher levels at a higher level of the stack.

  • The error code is easy to be ignored, and in most cases.

  • The rich information that is abnormal can describe the cause of the error.

  • Anomaly is allowed to face non -processed anomalous processors.

    The "processor that is not treated" here refers to​、Support abnormal treatment incidents that subscribe to global.

  • The development of abnormal promotion tools. Abnormality is a model that defines a clear method. Because of this, tools, analyzers, performance counter and other tools may pay close attention to abnormalities.

2. Example of abnormal use

The pseudo code in the previous section was changed to use abnormalities as follows:

try
 {{
     Client value = new client ();
     ();
     string content = ();
 }
 catch (Exception EX)
 {{
     ();
 }

 class client
 {{
     public void connect ()
     {{
         // Execute other actions
         If (SuccessEded)
         {{
             Return;
         }
         else
         {{
             // Execution failure, throw abnormal
             Throw New InvalidOperationException ("Because ..., the connection fails.");
         }
     }

     Public String Receive ()
     {{
         If (SuccessEded)
         {{
             Return result;
         }
         else
         {{
             Throw New InvalidOperationException ("Because ..., the data fails.");
         }
     }
 }

Earlier, we also mentioned that the return error code cannot be used in the scene without return value. The following is a simple example of using abnormal use in the constructing function and property setter:

class client
 {{
     Public BOOL Isconnect {get; Private Set;}
     Private String_Hostname;
     Private int _Port;

     // Through abnormal restrictions of hostname and port, they can only be modified without connecting.
     public string hostname
     {{
         get => _hostname;
         set
         {{
             if (iSconnect)
             {{
                 Throw New InvalidoperationException ("The client is in a connected state and cannot modify the host name."););
             }
             _hostname = value;
         }
     }

     public int port
     {{
         get => _Port;
         set
         {{
             if (iSconnect)
             {{
                 Throw New InvalidOperationException ("The client is in a connection state and cannot modify the port."););
             }
             _Port = value;
         }
     }

     Public Client (String Hostname, Int Port)
     {{
         if (hostname))
         {{
             Throw new argumentexception ("parameter invalid.", nameof (hostname);
         }
         Hostname = hostname;
         Port = port;
     }

     public void connect ()
     {{
         Isconnected = true;
     }
 }

It can be seen that the error code is more neat and cleaned through abnormal feedback, and can pass the abnormalitiesMessageProperties report error information.

3. Which exception should be thrown?

For abnormalities, simple use is not complicated. But there are many types of abnormalities, and developers often confuse which abnormalities should be thrown out. Abnormal and error -related, errors are generally divided into two categories:

  • Error

  • Error

    Divided into two categories:

    • Program error
    • System failure

Error: Error caused by error calls, such as passing into the NULL parameter. Such errors should not be processed by the framework, but the call party code should be modified.

There are 3 commonly used abnormalities corresponding to such errors:

  • ArgumentException​:ArgumentNullExceptionHarmonyArgumentOutOfRangeExceptionThe base class is used to indicate the parameter error
  • ArgumentNullException: The parameters are empty abnormalities. When the parameter of the transmission method is null, this exception should be thrown out
  • ArgumentOutOfRangeException: The parameter value exceeds the range of abnormal range. When the parameters of the passing method exceed the limited range, this exception should be thrown out

The following is a simple example:

class client
 {{
     Public Void Connect (String Hostname, Int Port)
     {{
         if (hostname))
         {{
             Throw new argumentexception ("parameter invalid.", nameof (hostname);
         }
         // Execute other operations
     }
 }

Execution error-program error: Error that can be treated in the program. likeNo corresponding files are thrown outFileNotFoundExceptionOdx, we can create a new file and continue to run.

There are many abnormalities corresponding to such errors. The most commonly used abnormalities are:

  • InvalidOperationException: When the object is in an incorrect state, throw this abnormality

The following is a simple example:

class client
 {{
     Public BOOL Isconnect {get; Private Set;}

     public void connect ()
     {{
         if (iSconnect)
         {{
             Throw New InvalidOperationException ("The client has been connected.");
         }
         // Other operations
         Isconnected = true;
     }
 }

Execution error-system failure: The execution error cannot be processed in the program. For exampleOutOfMemoryException​。

There are many abnormalities corresponding to such errors, but these abnormalities should not be thrown by developers, but CLR is responsible. For example:

  • OutOfMemoryException: When the inner layer is allocated, the abnormalities are thrown. Only CLR can throw this abnormality

Info

For more abnormal categories, seeChapter 7 Abnormal -Hihaojie -Blog Park7.3 Use of standard abnormal types

4. Disdiotic capture

There are throws, naturally capture. Unusual capture is not complicated, but there are still many details to pay attention to. Here we have to clarify the abnormal capture through several questions. We assume the followingConnect()Method,:

void Connect (String Hostname)
 {{
     if (hostname is null)
     {{
         Throw new argumentnullexception (nameof (hostname));
     }
     // Execute other operations
 }

Let's mention it here:ArgumentExceptionBeArgumentNullExceptionHarmonyArgumentOutOfRangeExceptionFather.

  • Question 1: As follows, which paragraph can be compiled?
// code 1
 try
 {{
     Connect (null!);
 }
 catch (Argumentexception EX)
 {{
     ("Capture Argumentexception");
 }
 catch (ArgumentNullexception EX)
 {{
     ("Capture Argumentnullexception exception");
 }
// code 2
 try
 {{
     Connect (null!);
 }
 catch (ArgumentNullexception EX)
 {{
     ("Exception exception");
 }
 catch (Argumentexception EX)
 {{
     ("Capture Argumentexception");
 }
// code 3
 try
 {{
     Connect (null!);
 }
 catch (ArgumentNullexception EX)
 {{
     ("Exception exception");
 }
 catch (Argumentexception EX)
 {{
     ("Capture Argumentexception");
 }
 Catch (InvalidoperationException EX)
 {{
     ("Capture InvalidoperationException");
 }
  • Question 2: Will the following code output "Capture Argumentexception abnormalities"?
try
 {{
     Connect (null!);
 }
 catch (Argumentexception EX)
 {{
     ("Capture Argumentexception");
 }
  • Question 3: Which information will output the following code?
try
 {{
     Sentmessage ("Abnormal test.");
 }
 catch (Argumentexception EX)
 {{
     ("Capture Argumentexception");
 }

 Void SentMessage (String Message)
 {{
     try
     {{
         Connect (null!);
     }
     Catch (ARGUMENTOUUTOFRANGEEPTION EX)
     {{
         ("Capture the argumentoutOutoFRANGEEPTION exception");
     }
 }

Through the above problems, we can draw the following conclusions:

  1. When the abnormalities to capture the relationship between the father and son, the sub -class is abnormal, and the parent class is abnormal, otherwise it will not be compiled;

  2. Sub -class abnormalities can be captured by capturing parent class abnormalities;

    ExceptionAs all abnormal bases, capture it can capture all abnormalities.

  3. Uncaying abnormalities will be thrown further up;

Correspondingly, there are these conventions for capturing exceptions (standards):

  1. The processing method of the same way can capture their common parent class;

Such as "using errors" abnormalities (ArgumentExceptionThree brothers), their processing methods are the same (the code should be modified by the caller), which can be directly capturedArgumentExceptionDreatment of abnormalities.

There are similarOperationCanceledExceptionHarmonyTaskCanceledException

  1. Only capture the exception to know how to deal with;

For unknown abnormalities, it should be thrown up further and processed from the previous level.

The following code demonstrates the treatment of known abnormalitiesTimeoutException, Ignoring unknown abnormalitiesArgumentNullException

try
 {{
     Connect (hostname);
 }
 Catch (Timeoutexception EX)
 {{
     ("Connection timeout, try secondary connection");
     Connect (hostname);
 }

 void Connect (String Hostname)
 {{
     if (hostname is null)
     {{
         Throw new argumentnullexception (nameof (hostname));
     }
     // Execute other operations
     if (usedtime> (100))
     {{
         Throw New Timeoutexception ("The connection is more than 100s."););
     }
 }

5. Disposure of abnormal capture and throwing again

Sometimes when we capture abnormalities, we don't want to deal with it, but we want to record and throw it twice, or turn it to other abnormalities and throw it out. Let's compare the following three -paragraph code to see what is the difference between their secondary throwing:

Exception Holder = NULL;
 try
 {{
     try
     {{
         Throw New Exception ("Primitive abnormal");
     }
     catch (Exception EX)
     {{
         ();
         Holder = EX;
         Throw;
     }
 }
 catch (Exception EX)
 {{
     ();
     ();
     (Holder == EX);
 }
Exception Holder = NULL;
 try
 {{
     try
     {{
         Throw New Exception ("Primitive abnormal");
     }
     catch (Exception EX)
     {{
         ();
         Holder = EX;
         Throw ex;
     }
 }
 catch (Exception EX)
 {{
     ();
     ();
     (ex == Holder);
 }
Exception Holder = NULL;
 try
 {{
     try
     {{
         Throw New Exception ("Primitive abnormal");
     }
     catch (Exception EX)
     {{
         ();
         Holder = EX;
         Throw New Exception ("Throwing abnormalities", ex);
     }
 }
 catch (Exception EX)
 {{
     ();
     ();
     (Holder == EX);
 }

We can find the above code we can find:

  • Use directlythrowThrow it out:The attribute will retain the original stack information;
  • usethrow exPlusal throwing: The abnormality of the second throw is the same as the original example, butThe storage stack information is updated to the position of the secondary throwing;
  • usethrow new Exception()Throwing the second time: the anomalies were packaged in the second time,​、Many members have changed.

We can adopt the corresponding secondary throwing method as needed, but generally follow the following standards:

  1. If you don't need to be abnormal in the second packaging, you should use it directlythrowThrow it out;
  2. If you need to be abnormal in secondary packaging, you should use itthrow new SomeExceptionThrow abnormalities in the secondary and put abnormal abnormalities into new abnormalities.

You may be confused about the phrase "and pass the abnormality into the new abnormality." Here we look at the base class abnormalitiesExceptionFour constructors:

public Exception();
public Exception(string message)
public Exception(string message, Exception innerException)
protected Exception(SerializationInfo info, StreamingContext context)

The third structure functionException(string message, Exception innerException)Need oneExceptionExample, yes, this parameter is specifically used for second packaging abnormalities. When we need to pack the original abnormality as other abnormalities, we need to pass the original abnormal instance through this parameter. This parameter is also possible when the second packaging is passed in, but it is a standard approach, which is conducive to developers to trace anomalies. The following is a simple example:

try
 {{
     Throw New Timeoutexception ("execution timeout.");
 }
 catch (Exception EX)
 {{
     Throw New InvalidOperationException ("If the execution fails, check the hardware status.", ex);
 }

6. Common abnormalities

Let's introduce common abnormalities and their usage scenarios.

6.1 Base class abnormalities

The following abnormalities are not clear due to the abnormal classification of expression, and the developer should not throw the following abnormalities:

  • Exception: Base class abnormalities, it is all abnormal base classes. When we customize abnormalities, we need to derive from this class or its subclasses.
  • ApplicationExceptionHarmonySystemException: At the beginning of the design,SystemExceptionThe derivative class is used to represent the abnormality of the CLR (or system) itself,ApplicationExceptionThe derivative class is used to indicate non -CLR abnormalities (application abnormality). But many abnormal classes do not follow this model, such asTargetInvocationExceptionDeriveApplicationException, But thrown by CLR. thereforeApplicationExceptionIt has lost its original meaning.

When we are custom abnormal, we no longer recommend itApplicationException​、SystemExceptionFor the base class.

6.2 Commonly used abnormalities

  • InvalidOperationException: If the object is in an incorrect state, throw this exception.

    For example: read onlyFileStreamWrite data.

  • ArgumentException​、ArgumentNullException​、ArgumentOutOfRangeException: When the user passes the error parameter, throw it outArgumentExceptionOr its derived class, and set it upParamNameProperties. If possible, try to choose an abnormal type located at the end of the inheritance level.

  • OperationCanceledException​、TaskCanceledException: It means that the operation is canceled.TaskCanceledExceptionUsed for asynchronous programming,OperationCanceledExceptionCan be used for any scene.

    It should be noted that it is manually thrown in the asynchronous methodTaskCanceledExceptionAt the same time, you need to pass through its constructorCancellationTokenOtherwiseTaskOutStatusThe attribute will not be marked asCanceled

  • FormatException: The input string in the text analysis method does not meet the requirements or the specified format.

  • FileNotFoundException: It means that the file is not found.

  • InvalidCastException: Indicate invalid type conversion, commonly in compulsory conversion and boxing.

    The following code will throw this exception:

    object content = ;
    int value = (int)content;
    
  • NotSupportedException: It means that the current member's function is not supported.

    byReadOnlyCollection<T>For example, it does not supportAdd()Method, but realized againIList<T>Interface, so itAdd()The method was thrown out of this exception.

  • NotImplementedException: It means that the current membership function has not yet been realized.

  • TimeoutException: Express the timeout. Due to historical reasons, the web communication timeout did not throw the exception. byWebRequestFor example, it will be thrown out by the communication timeoutWebExceptionAbnormal and abnormal instanceStatusAttribute valueEap the value.

6.3 CLR abnormal

Such abnormalities are usually thrown by CLR, and developers should not use these abnormalities.

  • NullReferenceException​、IndexOutOfRangeException​、AccessViolationException: It means that the code is defective, and the developer needs to adjust the code.
  • *Exception: This exception is thrown when the stack is overflow, which is common in infinite recursive. When the stack is overflowing, it is almost impossible to keep the custody code consistent. The abnormal CLR2.0 default will stop the program immediately. Developers should not capture this exception (yes, at this time, the program crash should be performed).
  • OutOfMemoryException: Memory allocation fails. This exception will be thrown.

7. How to customize abnormalities

In the previous section, we talked about many predefined abnormalities. When the predefined abnormalities could not meet our needs, we need to customize abnormalities.

Customized abnormalities usually follow the following standards:

  • Customized abnormalities should be derivedOr other commonly used base class abnormalities;

  • The inheritance level should not be too deep;

  • Named using the "Exception suffix;

  • If multiple errors can be treated in one way, they should belong to the same type of abnormalities;

  • Customized abnormalities should have at least 4 constructors:

    Public class someException: Exception, ISerializable
     {{
         public someException ();
         Public someexcepiton (String Message);
         Public someexcepiton (String Message, Exception Inner);
    
         // The constructor required for serialization
         Protected someException (SerializationInfo Info, StreamingContext Context);
     }

Tips

Regarding custom abnormalities, binary serialization must be achieved (that is, implementationSomeException(SerializationInfo info, StreamingContext context)Construct function) No longer required in the new version .NET, andException(SerializationInfo info, StreamingContext context)It is also marked for discarding ([Obsolete]To. Therefore, the following example ignores the realization of binary serialization.

Now, we assume that there is such a hardware device:

  • It is a ranging meter, and the computer communicates with it through TCP/IP (it is the server);
  • When it is being measured, the measuring instructions are repeatedly sent to respond (that is, a communication timeout will occur);
  • If the measurement distance exceeds returning, it will return the "Outofrange" string;
  • If the measurement is successful, the value will return, indicating the measured distance.

Here we have to customize oneDeviceErrorExceptionIt means all abnormalities when operating the hardware. Please think, how should the category of the ranginger be defined? How is this abnormal definition?

The following is a ranging class and correspondingDeviceErrorExceptionAbnormal, everyone can be used as a reference:

Class MeaSuerr
 {{
     Private tcpclient_client;
     Public BOOL isconnect => _Client! = Null &&_Client.connect;
     Private const string commit = "Measure";
     Private Const String Outofrangresponse = "Outofrange";

     Public Void Connect (String Hostname, Int Port)
     {{
         try
         {{
             _Client = New TCPClient (hostname, port);
         }
         Catch (Timeoutexception EX)
         {{
             Throw New DeviceErrorexception ("connection timeout.", ex,);
         }
     }
  
     public double measure ()
     {{
         try
         {{
             if (! isconnect)
             {{
                 Throw New Deviceerrorexception
             }

             byte [] writeBuffer = (Command);
             Stream stream = _Client.getstream ();
             _Client.getstream (). Writebuffer, 0,);
        
             byte [] readbuffer = new byte [100];
             int count = (readbuffer, 0,);
             string content = (readbuffer, 0, count);
             if (content == OUTOFRANCESPONSE))
             {{
                 Throw New Deviceerrorexception
             }

             If (Content, out Double Result))
             {{
                 Return result;
             }

             Throw New DeviceErrorexception ($ "to change the data failure. The content obtained is: [{content}],);
         }
         Catch (Timeoutexception EX)
         {{
             Throw New Deviceerrorexception ("Communication timeout.", ex,);
         }
         catch (deviceerrorexception)
         {{
             Throw;
         }
         catch (Exception EX)
         {{
             Throw New Deviceerrorexception
         }
     }
 }

 class deviceerrorexception: InvalidOperationException
 {{
     public deviceState State {get;}

     public deviceerrorexception (): this (): this ()
     {}

     Public DeviceRrorexception (DeviceState State)
     {{
         State = state;
     }
  
     Public DeviceErrolXception (String Message): This (MESSAGE,)
     {}

     Public DeviceRrorexception (String Message, DeviceState State): Base (Message)
     {{

         State = state;
     }
  
     Public DeviceErReRorexception (String Message, Exception Innexception): this (Message, Innexception,), incexception,),),),),),),)
     {}
  
     Public DeviceRorexception (String Message, Exception Incexception, DevicesState State): Base (MESSAGE, Incexception)
     {{
         State = state;
     }
 }

 enum deviceState
 {{
     Unknown,
     DataParseerror,
     Notconnected,
     Timeout,
     OutoFRANGE,
 }

8. Abnormal and performance

Some developers are unwilling to use abnormalities to use abnormalities: affecting performance (personal decision is a bit nonsense, at least in the field of industrial control, I think this performance loss is completely unnecessary).

The "Framework Design Guide" mentioned that when the frequency of abnormal abnormality is higher than 100 per second, it is likely to bring significant performance effects. At this time, we can use the "Tester-Executive Mode" or "TRY mode", which are very common in .NET.

8.1 Tester-Executive Mode:

We take the collection as an example. We don't know the following codenumbersWhether it is a collection of collection, so it may throw it outNotSupportException​:

ICollection<int> numbers = ...
(1);

ICollection<T>Just definedIsReadOnlyAttributes, we can first determine whether the set is read only, and then perform ADD operation:

ICollection<int> numbers = ...
...
if (!)
{
    (1);
}

in,IsReadOnlyIs a "tester",Add()The method is "executor".

In "7. How to customize abnormalities", I defineMeasurerThe class also addedIsConnectedAttributes, to inform whether the hardware has been connected, this is also a "tester-executor mode".

Notice

"Competitive conditions" may appear in multi -threaded mode, and pay more attention when used.

8.2 TRY mode

The use of TRY mode is more common, such as()​、Dictionary<TKey, TValue>.TryGetValu()Wait.

byDateTimeTry mode as an example, the general form is as follows:

public struct DateTime
{
    public static DateTime Parse(string dateTime) { ... }
    public static DateTime TryParse(string dateTime, out DateTime Result) { ... }
}

There are many details to pay attention to the TRY mode:

  • If members may throw abnormalities in common code, they should use the TRY-PARSE mode to avoid performance problems caused by abnormalities.

  • The TRY-PARSE mode should use the "TRY" prefix and use BOOL as the return type.

  • TRY method returnfalseThere is only one reason, and the remaining categories of failure should be thrown abnormal.

  • To provide the TRY method with an equivalent method.

    like()Equivalence()

  • Back the value of the TRY method through the OUT parameters.

  • When the TRY method returns FALSE, the default (t) is assigned to the OUT parameters.

  • Avoid writing data to the out parameter of the TRY method when throwing abnormality.

9. How to deal with the abnormality of "I don't know how to deal with it"

What should I do when the interface you call is thrown out of the unknown abnormality? The answer may be unexpected by most people: Do not capture it and let the program collapse is the best solution. There is such a paragraph in the "Framework Design Guide":

Your application should only deal with the abnormalities it understands. Generally speaking, after the problem of "something", it is almost impossible to restore the application from a state that may have been destroyed to normal. At this time, you only need to deal with the abnormalities that your application can respond reasonably. For all other abnormalities, no need to deal with, the operating system can suspend your application.

If you think that the current application is already ill and it should not continue to run, it is recommended to call()Methods to stop the process, not abnormal. This method accepts a string parameter, we can pass the error message through this parameter. This error message will eventually be recorded by the operating system in "Computer Management → System Tools → Event Viewer → Windows Log → Application". The collapse of the procedure caused by unsealed abnormalities, the collapse information will also be recorded here.

Finally, according to the Windows log information, further check the cause of the collapse of the program and perform targeted repair.

()The usage is as follows:

("An irreparable exception occurred", ex)

10. Moved abnormalities

Sometimes we caught abnormalities and do not want to deal with it directly, and we don't want to throw it out, but want to transfer it to other threads. Use a field/attribute to record this abnormality, and then throw it on the main thread? Not very suitable, this will destroy the original calling stack information.

.NET had been prepared for a long time, it provided itExceptionDispatchInfoClass, specifically used to transfer abnormalities:

When transferring abnormality from other threads, or if the empty Throw statement that is not emptied after CATCH is thrown out again, it is necessary to use it again.ExceptionDispatchInfoClass, it will continue to save the call stack in the process of reorganization. The following is a simple case:

Private ExceptiondispatchInfo_saveDexceptionInfo;

 Private void backgroundworker () {
     try {
         Elastic
     } Catch (Exception E) {{
         _savedexceptionInfo = (E);
     }
 }

 public object getresult () {
     if (_done)
         if (_SaveDexceptionInfo! = NULL) {
             _savedexceptionInfo.throw ();
             // The compiler cannot understand that this method is thrown out an exception, so an additional RETURN statement is needed.
             Return null;
         }
     }
 }

11. Filter abnormalities

Exception Filter is introduced in C#6. Through abnormal filter, we can repeatedly capture the same type of abnormalities:

catch (WebException ex) when ( == )
{ ... }
catch (WebException ex) when ( == )
{ ... }

The Boolean expression in WHEN clause can include side effects, such as calling a method to record the abnormal logs required for diagnosis.

It also has traps. Try analysis what will happen in the following code:

try
 {{
     throw new argumentexception ();
 }
 Catch (Argumentexception EX) when (==)
 {{
     ("The first when the first when the clause" was hit ");
 }
 catch (argumentexception ex) when (is null) (is null)
 {{
     ("Hit the Second WHEN clause");
 }

The answer is: the "hit the second WHEN clause" will be output.

You might be confused: Shouldn't it throw an exception in the first WHEN sentence? After all, the Paramname attribute is not assigned, and it should be thrown when an equal judgmentNullReferenceExceptionRight. This is because the abnormality is captured by the CLR when it causes abnormality in the filter and the filter returns FALSE. The behavior cannot be separated from the filter and returned to FALSE, so it is difficult to debug. Pay more attention when using

12. Other matters

12.1 Do not modify the abnormal name and its father class at will

We mentioned earlier:

The processing method of the same way can capture their common parent class

This means that we should not modify custom abnormal base classes at will, otherwise the original abnormal processing code cannot work properly. Take the following code as an example, because the base class is abnormalInvalidOperationExceptionChange toException, The original abnormal processing code no longer works:

//
 // Class MyException: InvalidOperationException {}
 // Modify the abnormality after the base class
 Class MyException: Exception {}

 // The abnormal processing code that can originally operates is invalidated
 try
 {{
     Throw new myexception ();
 }
 Catch (InvalidoperationException EX)
 {{
     ("Capture InvalidoperationException or its sub -class abnormalities");
 }

12.2 The exception that will still be thrown up after capture:ThreadAbortException

It is obviously inseparable from the multi -threaded threadThread​。ThreadOutAbort()Methods used to terminate the corresponding thread, and the terminate thread will throw it outThreadAbortExceptionAbnormal. However, the exception is more special, and it will continue to throw it up after the capture. Try the following code, what will happen:

Thread Thread = New Thread (Dosomething);
 ();
 (100);
 ();

 void dosomething ()
 {{
     try
     {{
         try
         {{
             While (true)
             {{
                 (20);
             }
         }
         Catch (Threadabortexception EX)
         {{
             ("The first time to get Threadabortexception exception");
         }
     }
     Catch (Threadabortexception EX)
     {{
         ("The second capture to the Threadabortexception exception");
     }
 }

The answer is: it will output "the first time to the Threadabortexception exception" and "the second capture to the Threadabortexception exception". If you want to terminate the abnormality and throw it out further, you need to call()Methods, it will bring thread status (ThreadState)AbortRequestedReturn toRunning​。


References:

  1. "Framework Design Guide: Construction, Construction, Customer and Mode of Construction of Reuse .NET Library"
  2. "C#7.0 Core Technology Guide"

Info

For some of the above two books, please refer to my reading notesReading Note Catalog Summary -Hihaojie -Blog Park