5
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 ArgumentOutOfRangeException exception type.
The ArgumentOutOfRangeException
exception is thrown when the argument passed to a method is not null
and contains a value that is not within the set of expected values. This exception type has the properties ParamName and ActualValue which helps understand the cause of the exception. The ParamName
property identifies the parameter name of the invalid argument and the ActualValue
property identifies the invalid value if a value is present.
The ArgumentOutOfRangeException
exception would normally result from developer error and if the value of the argument is returned by a method call or input from the user before being passed to the method that throws the exception, you should validate arguments before passing them to the method. The ArgumentOutOfRangeException
is used extensively by classes in the System.Collections
namespace. A typical scenario is when your code wants to remove an item at a certain index from a collection and the collection is either empty or the index you specified through the argument is negative or higher than the size of the collection. The following example demonstrates this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
using System; using System.Collections.Generic; class Program { static void Main(string[] args) { try { var numbers = new List<int>(); var index = 0; Console.WriteLine("Removing item at index {0}", index); numbers.RemoveAt(index); } catch (ArgumentOutOfRangeException ex) { Console.WriteLine("Oh no! Something went wrong"); Console.WriteLine(ex); } } }
The example above displays the following output when you run it:
1 2 3 4 5 6
Removing item at index 0 Oh no! Something went wrong System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index at System.Collections.Generic.List`1.RemoveAt(Int32 index) at MyApp.Program.Main(String[] args) in /dotnet/MyApp/Program.cs:line 13
To prevent the exception, we can check whether the collection's Count
property is greater than zero and the index to remove it is also less than the value in Count
, before attempting to remove any member in the collection. We will update the code statement inside the try
block to read as follows:
1 2 3 4 5 6 7 8 9
var numbers = new List<int>() { 1, 2 }; var index = 2; Console.WriteLine("Attempting to remove item at index {0}", index); if (numbers.Count > 0 && index < numbers.Count) { numbers.RemoveAt(index); Console.WriteLine("Removed item at index {0}", index); }
That will help us avoid running into an exception. For more scenarios that leads to ArgumentOutOfRangeException
exception, read the docs.
While the ArgumentOutOfRangeException
is extensively used by classes in the System.Collections
and System.IO
namespaces, the Array class, and string manipulation methods in the String
class, we can also use it to throw exceptions in our code to signal that the value of an argument is outside of the expected range. Let's look at an example of how we can use it. Create a new Console application project and update Program.cs with the code below.
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
namespace MyApp { using System; class Program { static void Main(string[] args) { try { Console.WriteLine("Enter account name"); var name = Console.ReadLine(); Console.WriteLine("Enter opening balance"); var balance = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Opening account for {0}... \n", name); var account = new Account(name, balance); Console.WriteLine("Account opened for {0}", account.Name); } catch (ArgumentOutOfRangeException ex) { Console.WriteLine("Oh no! Something went wrong"); Console.WriteLine(ex); } } class Account { public Account(string name, int balance) { if (balance < 1200) throw new ArgumentOutOfRangeException(nameof(balance), balance, "The account balance can't be less than 1200"); Name = name; Balance = balance; } public string Name { get; private set; } public int Balance { get; private set; } } } }
In the code above, we have an Account
class with properties Name
and Balance
, and a constructor that accepts name
and balance
as parameters. When this constructor with balance
less than 1200, it'll throw an ArgumentOutOfRangeException
exception with the parameter name that caused the exception, the value of the argument, and message explaining the cause of the error. In the static Main
method we collect the name and balance from the user, then create an Account
object with those information.
If we run the application and enter a value less than 1200 for the balance, we will get an exception. The information below is what we get when we run the code with 900 as the balance.
1 2 3 4 5 6 7 8 9 10 11 12
Enter account name Philly Enter opening balance 900 Opening account for Philly... Oh no! Something went wrong System.ArgumentOutOfRangeException: The account balance can't be less than 1200 Parameter name: balance Actual value was 900. at MyApp.Program.Account..ctor(String name, Int32 balance) in /dotnet/MyApp/Program.cs:line 34 at MyApp.Program.Main(String[] args) in /dotnet/MyApp/Program.cs:line 18
The ArgumentOutOfRangeException
exception is thrown when the value of an argument is outside the expected range of values as defined by the invoked method. The ArgumentOutOfRangeException
exception normally results from developer error so when dealing with this kind of error, be sure to read the value of the properties Message
, ParamName
, and ActualValue
. If the value of the argument is returned from a method call or input from the user before being passed to the method that throws the exception, you should validate the arguments before passing them to the method.
We looked at a scenario where calling RemoveAt
method of a collection could cause this exception alongside how to resolve the error. I also showed an example that demonstrates when it'll be useful to throw the ArgumentOutOfRangeException
from your methods. This should leave you equipped to handle and utilise this exception type!
5