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 three of them. They are the ArgumentException exception type, the ArgumentNullException exception type, and the ArgumentOutOfRangeException exception type.
The ArgumentException type is thrown when a method argument receives an invalid argument value. This exception type inherits from the System.SystemException
class, which in turn derives from the System.Exception
base class. The code below is a sample application that throws the ArgumentException
type.
1using System;
2
3namespace MyApp
4{
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 Console.WriteLine("Enter first name");
10 var firstName = Console.ReadLine();
11
12 Console.WriteLine("Enter last name");
13 var lastName = Console.ReadLine();
14
15 try
16 {
17 var fullName = GetFullName(firstName, lastName);
18 Console.WriteLine($"Your fullname is {fullName}");
19 }
20 catch (ArgumentException ex)
21 {
22 Console.WriteLine("Oh no, Something went wrong");
23 Console.WriteLine(ex);
24 }
25 }
26
27 static string GetFullName(string firstName, string lastName)
28 {
29 if (firstName == "" || lastName == "") throw new ArgumentException ("first & last name arguments cannot be empty");
30 return $"{firstName} {lastName}";
31 }
32 }
33}
The GetFullName
method has two arguments, firstName
and lastName
, and it checks if either of the two is an empty string. If it evaluates either to be true, it throws an exception of type ArgumentException
. We used the constructor that takes the exception message as the only parameter. The exception message we set above won't be very helpful in knowing which argument caused the exception. Wouldn't it be better if we can tell which argument caused the error, making it easier to fix the error?
The ArgumentException
class has a ParamName
property which identifies the invalid argument. This will be the name of the argument. With this knowledge, we can update the GetFullName
method as follows.
1static string GetFullName(string firstName, string lastName)
2{
3 if (firstName == "") throw new ArgumentException("empty string is an invalid value", "firstName");
4 if (lastName == "") throw new ArgumentException("empty string is an invalid value", "lastName");
5
6 return $"{firstName} {lastName}";
7}
If you run the application and pass an empty string for the first name, you'll get the following error:
1Oh no, Something went wrong
2
3System.ArgumentException: empty string is an invalid value
4Parameter name: firstName
5 at MyApp.Program.GetFullName(String firstName, String lastName) in /Users/pmbanugo/Documents/projects/dotnet/MyApp/Program.cs:line 30
6 at MyApp.Program.Main(String[] args) in /Users/pmbanugo/Documents/projects/dotnet/MyApp/Program.cs:line 17
You can see that it prints the exception message alongside the parameter name.
The ArgumentNullException
exception type derives from the ArgumentException
class. This type of exception is thrown when a null value is passed to a method argument and null is not allowed for that argument. To illustrate, let's create a console application and update Program.cs with the following code:
1using System;
2
3namespace MyApp
4{
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 try
10 {
11 var user = new User(null, 23);
12 }
13 catch (ArgumentNullException ex)
14 {
15 Console.WriteLine("Oh no, Something went wrong");
16 Console.WriteLine(ex);
17 }
18 }
19
20 class User
21 {
22 public User(string userName, int age)
23 {
24 if (userName == null)
25 throw new ArgumentNullException(nameof(userName), "username is invalid");
26
27 UserName = userName;
28 Age = age;
29 }
30 public string UserName { get; private set; }
31 public int Age { get; private set; }
32 }
33 }
34}
We define a User
class with properties UserName
and Age
. In the class constructor we accept two parameters and assign them to the appropriate properties. Before the assignment, we check if userName
is null. If it is, we throw an ArgumentNullException
exception. We called the constructor of ArgumentNullException
that accepts the parameter name that caused the exception and a second parameter representing the exception message. You might have noticed we used the nameof operator to get the string name of the parameter that caused the exception. Using nameof
operator helps keep your code valid when renaming definitions.
If you run the application, it'll throw an exception because userName
is null. It'll print the exception info in the console.
1Oh no, Something went wrong
2
3System.ArgumentNullException: username is invalid
4Parameter name: userName
5 at MyApp.Program.User..ctor(String userName, Int32 age) in /Users/pmbanugo/Documents/projects/dotnet/MyApp/Program.cs:line 27
6 at MyApp.Program.Main(String[] args) in /Users/pmbanugo/Documents/projects/dotnet/MyApp/Program.cs:line 11
The ArgumentOutOfRangeException
type is a subclass of ArgumentException
class. This exception type is thrown when the value of an argument is outside of the allowable range. For example, this can be thrown when you pass negative numbers to a function that accepts only positive numbers.
To demonstrate the usage of this type, we will continue with the sample application from the previous section. Edit the constructor of the User
class as follows:
1public User(string userName, int age)
2{
3 if (userName == null)
4 throw new ArgumentNullException(nameof(userName), "username is invalid");
5 if (age < 18 || age > 50)
6 throw new ArgumentNullException(nameof(age), "age is outside the allowable range");
7
8 UserName = userName;
9 Age = age;
10}
The code above throws an exception when the age argument is less than 18 or greater than 50.
Exceptions can be thrown either by the runtime or the application code. This can be caused by bad code while, other times, the problem is caused by bad user input that has not been accounted for in the application’s code. In this guide, we looked at three commonly encountered exception types. They are ArgumentException
, ArgumentNullException
and ArgumentOutOfRangeException
. They can be thrown by the common language runtime (CLR) or another class library and indicates developer error.