常见异常-InvalidOperationException
介绍
异常是程序中违反系统或应用程序约束的运行时错误,或者是程序正常执行期间不应发生的情况。异常的可能原因包括尝试连接到不再存在的数据库、程序试图将数字除以零或打开损坏的 XML 文件。当发生这些情况时,系统会捕获错误并引发异常。捕获异常是一种处理这些意外错误的方法,方法是定义在引发异常时运行的代码块。
有一些常见的异常类型值得注意。在本指南中,我们将介绍InvalidOperationException异常类型。
遇到 InvalidOperationException 异常类型
当方法调用对于对象的当前状态无效时,会引发 InvalidOperationException 异常类型。引发InvalidOperationException异常的一些常见原因包括:
- 从非 UI 线程更新 UI 线程。
- 迭代时更改集合。
- 对无法比较对象的数组或集合进行排序。
- 将为空的 Nullable 转换为其基础类型。
- 在空集合上调用 System.Linq.Enumerable 方法。
让我们看一个在迭代集合时向其添加项目的示例。创建一个新的控制台应用程序项目。打开Program.cs并将以下代码放入其中:
using System;
using System.Collections.Generic;
namespace MyApp
{
class Program
{
static void Main(string[] args)
{
try
{
var accounts = new List<Account>() {
new Account("Jimmy Gradle", 900),
new Account("Sophie Gradle", 300)
};
Console.WriteLine("Looping through available accounts");
foreach (Account account in accounts)
{
Console.WriteLine("{0} has {1} dollars", account.Name, account.Balance);
if (account.Name == "Sophie Gradle")
{
var newAccount = new Account("Jeremy brown", 1500);
Console.WriteLine("Adding {0} to the collection...\n", newAccount.Name);
accounts.Add(newAccount);
}
}
}
catch (InvalidOperationException ex)
{
Console.WriteLine("Oh no, Something went wrong");
Console.WriteLine(ex.Message);
}
}
class Account
{
public Account(string name, int balance)
{
Name = name;
Balance = balance;
}
public string Name { get; private set; }
public int Balance { get; private set; }
}
}
}
从上面的代码中,我们定义了一个Account类。在Main方法中,我们有一个Account类型的集合,在循环遍历它时,我们将当前帐户详细信息打印到控制台,然后将一个新的Account对象添加到集合中。如果我们按原样运行程序,我们将得到以下结果。
Looping through available accounts
Jimmy Gradle has 900 dollars
Sophie Gradle has 300 dollars
Adding Jeremy brown to the collection...
Oh no, something went wrong
Collection was modified; enumeration operation may not execute.
在foreach语句中向集合添加新项时,我们遇到了错误。这是因为用于迭代集合成员的foreach语句只允许您读取或修改单个项,而不能从集合中添加或删除项。为了修复我们遇到的错误(因为我们无法在迭代集合时向集合添加项),我们将使用 for 语句并按其索引进行迭代。
使用以下内容更新try块内的代码:
var accounts = new List<Account>() {
new Account("Jimmy Gradle", 900),
new Account("Sophie Gradle", 300)
};
Console.WriteLine("Looping through available accounts");
int count = accounts.Count - 1;
for (int index = 0; index <= count; index++)
{
var account = accounts[index];
Console.WriteLine("{0} has {1} dollars", account.Name, account.Balance);
if (account.Name == "Sophie Gradle")
{
var newAccount = new Account("Jeremy brown", 1500);
Console.WriteLine("Adding {0} to the collection… \n", newAccount.Name);
accounts.Add(newAccount);
}
}
修复方法是将枚举从正在更改的集合中分离出来。我们获取了集合中的项目数,并使用它来创建for循环语句。运行应用程序时,它应该运行无任何错误,并将以下内容输出到控制台:
Looping through available accounts
Jimmy Gradle has 900 dollars
Sophie Gradle has 300 dollars
Adding Jeremy brown to the collection...
引发 InvalidOperationException 异常类型
在上一节中,我们看到,当方法调用对于对象的当前状态无效时,会抛出InvalidOperationException异常类型。如果我们想向应用程序发出信号,表示无法执行通过方法调用请求的操作,因为对象处于执行该操作的无效状态,我们也可以抛出此异常类型。继续上一节中的示例项目,假设我们有一个新的要求,允许对帐户进行提款交易。如果提款金额高于帐户余额,交易应该失败。我们将通过添加新的Withdraw方法来更新Account类,如下所示:
public void Withdraw(int amount)
{
Console.WriteLine("Withdrawing {0} from the {1}'s account", amount, Name);
if (amount > Balance)
throw new InvalidOperationException("Insufficient fund");
Balance = Balance - amount;
Console.WriteLine($"Transaction completed. Account Balance is {Balance}");
}
该方法检查提款金额是否大于余额。如果是,则抛出InvalidOperationException异常并显示“资金不足”的消息。否则,它会从余额中扣除金额。
将静态Main方法中的try块中的代码更新为:
try
{
var account = new Account("Jimmy Gradle", 900);
for (int i = 0; i <= 5; i++)
{
var amount = 300;
account.Withdraw(amount);
Console.WriteLine("Withdrawn {0} from the {1}'s account. \n", amount, account.Name);
}
}
上面的代码创建了一个Account对象和一个迭代五次的循环。每次迭代时,都会通过调用Withdraw方法从帐户中扣除300 元。运行该应用程序,您将在控制台中看到类似以下内容:
Withdrawing 300 from the Jimmy Gradle's account
Transaction completed. Account Balance is 600
Withdrawn 300 from the Jimmy Gradle's account.
Withdrawing 300 from the Jimmy Gradle's account
Transaction completed. Account Balance is 300
Withdrawn 300 from the Jimmy Gradle's account.
Withdrawing 300 from the Jimmy Gradle's account
Transaction completed. Account Balance is 0
Withdrawn 300 from the Jimmy Gradle's account.
Withdrawing 300 from the Jimmy Gradle's account
Oh no, Something went wrong
System.InvalidOperationException: Insufficient fund
at MyApp.Program.Account.Withdraw(Int32 amount) in ~/dotnet/MyApp/Program.cs:line 42
at MyApp.Program.Main(String[] args) in ~/dotnet/MyApp/Program.cs:line 18
在第四次循环时,我们得到了一个InvalidOperationException异常,其消息为Insufficient fund。从控制台输出中,您应该注意到第三次迭代使帐户余额为零,因此,在第四次迭代中调用Withdraw导致了此异常。
结论
如果方法调用失败是由于参数无效以外的原因导致的,则会引发 InvalidOperationException 异常。通常,当对象的状态无法支持方法调用时,会引发该异常。由于InvalidOperationException异常可能在各种情况下引发,因此阅读Message属性返回的异常消息非常重要。如何处理异常取决于具体情况。然而,最常见的情况是,异常是由开发人员的错误导致的,这是可以预料和避免的。
我们查看了一个例子,展示了何时从代码中抛出InvalidOperationException是有用的。这应该让你能够处理和利用这种异常类型。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~