SoFunction
Updated on 2025-03-07

Miscellaneous Try-catch-finally exception handling

Related readings:Talking about exception handling try catch finally

1. Preface

Recently, a store management system has been developed, and this project is positioned as a software system for small and medium-sized stores. Simply put, it handles the functions of purchasing, selling, returning goods and other products. Although the software is small, it has all the internal organs, and the technologies involved are actually not much different from those of large application software, including encryption, data access, exception handling, logging, verification, ORM, dependency injection, etc.

This article mainly introducesContents of exception handling in C# language, which contains the main content:

•What is an exception? What are the characteristics of the exception?
• Basic knowledge of exception handling.
• Handling guidelines for raising and catching exceptions.
•Two design patterns to avoid performance problems related to exceptions.
•Microsoft Enterprise Library Exception Handling Module.

2. Anomaly Overview

•Exception will occur when an application encounters an exception (such as a divisor or an insufficient memory warning).
•Use try blocks around statements that may throw exceptions.
•After an exception occurs in the try block, the control flow will jump to the associated exception handler (if present).
•If there is no exception handler for the given exception, the program will stop executing and an error message is displayed.
•If the catch block defines an exception variable, you can use it to get more information about the type of the exception that occurred.
•The operation that may cause exceptions to be performed through the try keyword.
•Exception handler is a block of code that is executed when an exception occurs. In C#, the catch keyword is used to define exception handlers.
•The program can use the throw keyword to explicitly throw exceptions.
•Exception object contains detailed information about the error, such as the state of the call stack and text descriptions about the error.
• Even if an exception is raised, the code in the finally block will be executed, allowing the program to free up resources.

3. Basic knowledge of exception handling

3.1. How to: Use Try/Catch block to catch exceptions

Place the section of the code that may throw an exception in the Try block, and place the code that handles the exception in the Catch block. A Catch block is a series of statements that start with the keyword catch, followed by an exception type and the action to be performed.

The following code example uses the Try/Catch block to catch possible exceptions. The Main method contains a Try block with a StreamReader statement that opens a data file named and writes a string from that file. Following the Try block is a Catch block that catches any exceptions generated by the Try block.

using System;
using ;
using ;
// Security permission request.
[assembly:FileIOPermissionAttribute(, All = @"c:\")]
public class ProcessFile {
public static void Main() {
try {
StreamReader sr = ("");
("The first line of this file is {0}", ()); 
}
catch(Exception e) {
("An error occurred: '{0}'", e);
}
}
}

3.2. How to: Use a specific exception in a Catch block

When an exception occurs, the exception is passed up along the stack and each Catch block has a chance to handle it. The order of the Catch statements is important. Place the Catch block for a specific exception in front of the regular exception Catch block, otherwise the compiler may issue an error. The way to determine the correct Catch block is to match the type of the exception to the exception name specified in the Catch block. If there is no specific Catch block, the exception is caught by a regular Catch block that may exist.

The following code example uses the try/catch block to capture an InvalidCastException. This example creates a class named Employee with a property: Employee level. The PromoteEmployee method acquires the object and increases the staff level. An InvalidCastException occurs when passing a DateTime instance to the PromoteEmployee method.

using System;
public class Employee
{
//Create employee level property.
public int Emlevel
{
get
{
return(emlevel);
}
set
{
emlevel = value;
}
}
int emlevel;
}
public class Ex13
{
public static void PromoteEmployee(Object emp)
{
//Cast object to Employee.
Employee e = (Employee) emp;
// Increment employee level.
 =  + 1;
}
public static void Main()
{
try
{
Object o = new Employee();
DateTime newyears = new DateTime(2001, 1, 1);
//Promote the new employee.
PromoteEmployee(o);
//Promote DateTime; results in InvalidCastException as newyears is not an employee instance.
PromoteEmployee(newyears);
}
catch (InvalidCastException e)
{
("Error passing data to PromoteEmployee method. " + e);
}
}
}

3.3. How to: Externally throw an exception

An exception can be thrown explicitly using the throw statement. You can also use the throw statement to throw the caught exception again. A better encoding practice is to add information to the re-raised exception to provide more information during debugging.

The following code example uses the try/catch block to capture possible FileNotFoundException. The try block is followed by a catch block. The catch block captures FileNotFoundException. If the data file cannot be found, a message is written to the console. The next statement is the throw statement, which raises a new FileNotFoundException and adds text information to the exception.

using System;
using ;
public class ProcessFile
{
public static void Main()
{
FileStream fs = null;
try 
{
//Opens a text tile.
fs = new FileStream(@"C:\temp\", );
StreamReader sr = new StreamReader(fs);
string line;
//A value is read from the file and output to the console.
line = ();
(line);
}
catch(FileNotFoundException e)
{
("[Data File Missing] {0}", e);
throw new FileNotFoundException(@" not in c:\temp directory]",e);
}
finally
{
if (fs != null)
();
}
}
}

3.4. How to: Use the Finally block

When an exception occurs, execution will be terminated and control will be handed over to the most recent exception handler. This usually means not executing lines of code that you want to always call. Some resource cleaning (such as closing files) must always be performed even if an exception occurs. To achieve this, you can use the Lastly block. The final block is always executed, regardless of whether an exception occurs.

The following code example uses the try/catch block to capture an ArgumentOutOfRangeException. The Main method creates two arrays and tries to copy one array to another. This operation generates an ArgumentOutOfRangeException, and an error is written to the console. Finally block execution, regardless of the result of the copy operation.

using System;
class ArgumentOutOfRangeExample
{
static public void Main()
{
int[] array1={0,0};
int[] array2={0,0};
try
{
(array1,array2,-1);
}
catch (ArgumentOutOfRangeException e)
{
("Error: {0}",e);
}
finally
{
("This statement is always executed.");
}
}
}

4. Abnormal design guidelines

4.1. Exception triggers

•Do not return error code. Exceptions are the main means of reporting errors in the framework.
•Do not use exceptions for normal control flow as much as possible. In addition to system failures and operations that may lead to contention states, framework designers should also design APIs so that users can write code that does not throw exceptions. For example, a method may be provided to check preconditions before calling a member so that the user can write code that does not throw an exception.
•Do not include public members that can raise or not raise an exception based on a certain option.
•Do not include public members that return exceptions as return values ​​or output parameters.
• Consider using the exception generator method. Raising the same exception from different locations often occurs. To avoid code bloating, use the helper method to create an exception and initialize its properties.
• Avoid explicitly throwing exceptions from finally blocks. Exceptions that are implicitly raised by calling the method that raises the exception can be accepted.

4.2. Exception handling

•Do not handle errors by catching non-specific exceptions (such as , , etc.) in framework code.
• Avoid handling errors by catching non-specific exceptions (such as , , etc.) in application code. In some cases, errors can be handled in the application, but this is extremely.
•If the exception is caught to transmit exceptions, do not exclude any special exceptions.
• If you understand the conditions raised by a particular exception in a given context, consider catching these exceptions.
•Do not use catch too much. Exceptions should usually be allowed to propagate upwards in the call stack.
•Use try-finally and avoid using try-catch for cleaning code. In exception codes for writing specifications, try-finally is far more commonly used than try-catch.
• When catching and throwing an exception again, it is preferred to use empty raising. This is the best way to keep the exception call stack.
•Do not use parameterless catch blocks to handle exceptions that do not conform to CLS (not derived exceptions). Languages ​​that support exceptions that are not derived from Exception can handle these CLS-incompatible exceptions.

5. Two design modes

5.1. Tester-Doer Mode

Doer Part

public class Doer
{
public static void ProcessMessage(string message)
{
if (message == null)
{
throw new ArgumentNullException("message");
}
}
}

Testerpart

public class Tester
{
public static void TesterDoer(ICollection<string> messages)
{
foreach (string message in messages)
{
if (message != null)
{
(message);
}
}
}
}

5.2. TryParse Mode

The TryParse method is similar to the Parse method, except that the TryParse method does not raise an exception when the conversion fails.

Parse method

public void Do()
{
string s = “a”;
double d;
try
{
d = (s);
}
catch (Exception ex)
{
d = 0;
}
}

TryParse method

public void TryDo()
{
string s = "a";
double d;
if ((s, out d) == false)
{
d = 0;
}
}

6. Microsoft Enterprise Library Exception Handling Module

6.1. Create a custom exception wrapper class

public class BusinessLayerException : ApplicationException
{
public BusinessLayerException() : base()
{
}
public BusinessLayerException(string message) : base(message)
{
}
public BusinessLayerException(string message, Exception exception) :
base(message, exception)
{
}
protected BusinessLayerException(SerializationInfo info, StreamingContext context) :
base(info, context)
{
}
}

6.2. Configuring exception handling

<add name="Wrap Policy">
<exceptionTypes>
<add type=", , Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
postHandlingAction="ThrowNewException" name="DBConcurrencyException">
<exceptionHandlers>
<add exceptionMessage="Wrapped Exception: A recoverable error occurred while attempting to access the database."
exceptionMessageResourceType="" wrapExceptionType=", "
type=", , Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
name="Wrap Handler" />
</exceptionHandlers>
</add>
</exceptionTypes>
</add>

6.3. Write code

public bool ProcessWithWrap()
{
try
{
();
}
catch(Exception ex)
{
// Quick Start is configured so that the Wrap Policy will
// log the exception and then recommend a rethrow.
bool rethrow = (ex, "Wrap Policy");
if (rethrow)
{
throw; 
} 
}
return true;
}

summary

try { //Execute code, there may be exceptions. Once an exception is found, immediately jump to catch execution. Otherwise, the contents in the catch will not be executed }
catch { //Unless an exception occurs in the execution code in the try, the code here will not be executed }
finally { //It will be executed no matter what the situation is, including the use of return in try catch. It can be understood that as long as try or catch is executed, it will definitely be executed finally}