1
An exception is a runtime error in a program that violates a system or application constraint, or a condition that is not expected to occur during normal execution of the program. Possible causes of exceptions include attempting to connect to a database that no longer exists, when a program tries to divide a number by zero, or opening a corrupted XML file. When these occur, the system catches the error and raises an exception. Catching exceptions is a way of handling these unexpected errors by defining a block of code that will be run when an exception is thrown.
There are a few commonly encountered exception types that are useful to be aware of. In this guide, we will look at the InvalidOperationException exception type.
The InvalidOperationException
exception type is thrown when a method call is invalid for the object's current state. Some common causes of the InvalidOperationException
exception are:
Let's look at an example where we add items to a collection while iterating it. Create a new console application project. Open Program.cs and put the following code in it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
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; } } } }
From the code above, we defined an Account
class. In the Main
method we have a collection of Account
type and, while looping through it, we print the current account details to the console, then add a new Account
object to the collection. If we run the program as it is, we will get the following result.
1 2 3 4 5 6 7
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.
We encountered an error at the point of adding a new item to the collection inside the foreach
statement. This is because the foreach
statement, which is used to iterate members of a collection, only allows you to read or modify the individual items and not to add or remove items from the collection. To fix the error we are getting, because we can't add an item to a collection while iterating it, we will use the for
statement and iterate by its index.
Update the code within the try
block with the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
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); } }
The fix was to detach the enumeration from the collection that is changing. We got the count of items in the collection and used it to create the for
loop statement. When you run the application, it should run without any error and output the following to the console:
1 2 3 4
Looping through available accounts Jimmy Gradle has 900 dollars Sophie Gradle has 300 dollars Adding Jeremy brown to the collection...
In the previous section, we saw that the InvalidOperationException
exception type is thrown when a method call is invalid for the object's current state. We can also throw this exception type in cases where we want to signal to our application that the requested operation through a method call can't be performed because the object is in an invalid state to perform the operation. Carrying on from the example project from the previous section, let’s say we have a new requirement to allow withdrawal transactions on an account. If the withdrawal amount is higher than the account balance, the transaction should fail. We will update the Account
class by adding a new Withdraw
method as follows:
1 2 3 4 5 6 7 8
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}"); }
The method checks if the withdrawal amount is greater than the balance. If it is, it throws InvalidOperationException
exception with message saying Insufficient fund
. Otherwise, it subtracts the amount from the balance.
Update the code in the try
block in the static Main
method to be:
1 2 3 4 5 6 7 8 9 10 11 12
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); } }
The code above creates an Account
object and a loop that iterates five times. On each iteration, the amount of 300 is deducted from the account by calling the Withdraw
method. Run the application and you'll get something similar to the following in the console:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
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
We got an InvalidOperationException
exception with Insufficient fund
as the message when looping for the fourth time. From the console output, you should notice that the third iteration left the account with a balance of zero, therefore, calling Withdraw
on the fourth iteration caused this exception.
The InvalidOperationException
exception is thrown in cases where the failure to invoke a method is caused by reasons other than invalid arguments. Typically, it is thrown when the state of an object cannot support the method call. Because the InvalidOperationException
exception can be thrown in a wide variety of circumstances, it is important to read the exception message returned by the Message
property. How you handle the exception depends on the specific situation. Most commonly, however, the exception results from developer error and it can be anticipated and avoided.
We looked at an example that showed when it'll be useful to throw the InvalidOperationException
from our code. This should leave you equipped to handle and utilize this exception type.
1