理解、定义和使用自定义异常
介绍
编写软件是一项复杂的工作,即使是最好的软件也经常会出现各种问题。有时问题是由糟糕的代码引起的,有时问题是由应用程序代码中未考虑到的错误用户输入引起的。无论问题的原因是什么,最终结果都是应用程序无法按预期运行。此时,我们说应用程序遇到了错误。在 .NET 中,当正在运行的应用程序遇到错误时会引发异常。
什么是异常?
异常是程序中违反系统或应用程序约束的运行时错误,或者是程序正常执行期间不应发生的情况。可能的异常包括尝试连接到不再存在的数据库、程序尝试将数字除以零或打开损坏的 XML 文件。当发生这些情况时,系统会捕获错误并引发异常。
理解和定义自定义异常
.NET 提供了内置异常类,当我们的应用程序的业务规则被违反时,我们可以抛出这些异常。但是,如果这些内置异常类型都不能满足我们的需求,我们可以创建自己的异常类。我们在项目中定义的异常类就是所谓的自定义异常。如果您正在构建库或框架,并且希望该库的使用者对库中的异常的反应不同于内置异常类型的反应,则可以定义和使用自定义异常。另一个有用的场景是,如果您正在与某些外部服务交互,该服务会返回错误代码来指示错误。然后,您可以使用 Gateway或Facade设计模式之类的方法将错误代码转换为自定义异常。
实现自定义异常类时,它们应该从System.Exception类(或任何其他自定义异常类)继承。类名应该以 Exception 结尾,并且应该至少实现异常类型的三个通用构造函数。
让我们看一个能够在两个账户之间转移资金的示例应用程序。业务规则是,您不能贷记或借记被阻止的账户,这就是我们将抛出自定义异常的地方。创建一个新的控制台应用程序项目。添加一个文件AccountBlockedException.cs,其中包含以下类定义:
System.Serializable]
public class AccountBlockedException : System.Exception
{
private static readonly string DefaultMessage = "The transaction cannot be performed on a blocked account";
public string AccountName { get; set; }
public string TransactionType { get; set; }
public AccountBlockedException() : base(DefaultMessage) { }
public AccountBlockedException(string message) : base(message) { }
public AccountBlockedException(string message
我们定义了一个名为AccountBlockedException的自定义异常,它派生自System.Exception基类。它包含属性TransactionType和AccountName,以及一个默认消息变量,当构造函数未提供任何消息参数时,该变量将被设置为Message属性。前三个公共构造函数是异常类型的三个标准构造函数。其他构造函数接受参数accountName来指示帐户的所有者,并接受transactionType来指定导致错误的是信用交易还是借记交易。
使用自定义异常
自定义异常的抛出和捕获方式与 .NET 中预定义的异常类型相同。要使用我们定义的自定义异常,请向项目添加一个新文件Account.cs 。将以下代码复制并粘贴到其中。
class Account
{
public Account(string name, int balance)
{
Name = name;
Balance = balance;
}
public string Name { get; private set; }
public int Balance { get; private set; }
public bool IsBlocked { get; set; }
public void Credit(int amount)
{
if (IsBlocked)
{
throw new AccountBlockedException(Name, "Credit");
}
Balance = amount + Balance;
}
public void Debit(int amount)
{
if (IsBlocked)
{
throw new AccountBlockedException(Name, "Debit");
}
Balance = Balance - amount;
}
}
Account类是我们抛出AccountBlockedException自定义异常的地方。IsBlocked属性指示帐户是否被阻止。Credit和Debit方法在执行交易之前检查帐户是否被阻止。如果被阻止,它会抛出 AccountBlockedException异常,并使用构造函数来指定帐户名称和交易类型。
打开Program.cs文件并使用以下代码更新它:
class Program
{
static void Main(string[] args)
{
try
{
var accountToDebit = new Account("Francis John", 900);
var accountToCredit = new Account("Francisca Grey", 900);
BlockAccount(accountToCredit);
TransferFund(200, accountToDebit, accountToCredit);
}
catch (AccountBlockedException ex)
{
Console.WriteLine("Oh no! Something went wrong");
Console.WriteLine(ex.Message);
Console.WriteLine("Account name: {0}", ex.AccountName);
Console.WriteLine("Transaction type: {0}", ex.TransactionType);
}
}
static void BlockAccount(Account account)
{
account.IsBlocked = true;
}
static void TransferFund(int amount, Account accountToDebit, Account accountToCredit)
{
Console.WriteLine("Initiating transaction");
Console.WriteLine("Will debit account {0} for the sum of {1}... \n", accountToDebit.Name, accountToDebit.Balance);
accountToDebit.Debit(amount);
Console.WriteLine("Will credit account {0} for the sum of {1}... \n", accountToDebit.Name, accountToDebit.Balance);
accountToCredit.Credit(amount);
Console.WriteLine("Transfer fund transaction completed");
}
}
在此文件中,我们声明了BlockAccount方法来阻止帐户,并声明了TransferFund方法来在两个不同的帐户之间转移资金。在Main方法中,我们创建了两个帐户对象,通过调用BlockAccount(accountToCredit)阻止了其中一个帐户对象;并调用TransferFund方法来转移资金。运行此代码时,应该会生成一个异常(该异常将被 catch 块捕获)。运行该应用程序应该会在控制台中显示以下输出。
Initiating transaction
Will debit account Francis John for the sum of 900...
Will credit account Francis John for the sum of 700...
Oh no! Something went wrong
The transaction cannot be performed on a blocked account
Account name: Francisca Grey
Transaction type: Credit
这将引发异常,因为名为Francisca Grey的帐户已被阻止。AccountName和TransactionType属性已被证明可用于判断哪个帐户被阻止以及导致错误的交易类型。
包起来
自定义异常是您在项目中自己定义的异常类型。它们基本上继承自Exception基类并实现异常类型中的三个常见构造函数。它们可用于您正在构建库并且希望该库的用户正确处理从库中引发的异常的场景。我向您展示了一个示例,该示例指导您定义和使用自定义异常。这应该让您能够正确定义和使用自定义异常类型!
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~