In this article, we are going to learn about the type-testing as and is operators in C#.

Sometimes, when we code in a strongly-typed language like C#, the need arises to mix and match a little bit. That’s okay, as we can’t always foresee the path that the problem-solving aspect of programming will take us on. But whenever this happens, we must pick our options wisely.

For this reason, today we are going to see one of the many ways of casting and comparing types in C#: the type-testing operators.

To download the source code for this article, you can visit our GitHub repository.

Let’s start.

The “Is” Operator

The is keyword represents a built-in type comparison operator. As such, it will always return a boolean value when used. The way we use it is pretty similar to the basic == equality operator that everyone knows and loves, and both can be used to compare types:

var example = "This is a string";

var equalityComparison = example.GetType() == typeof(string);
var typeComparison = example is string;

Both expressions represent valid ways to check if a given object is of a certain type. But doing this type of comparison using the is operator is much easier than doing it with the == operator. It’s also easier for a human to read, which is something we should always strive for when writing code.

However, we should keep in mind that some cases in which the is operator will return true may not be evident at first. Consider an Animal class with a property that defines its eating habits, and a Cow class that inherits from the Animal class:

public class Animal
    public string EatingHabits { get; set; }

    public Animal(string eatingHabits)
        EatingHabits = eatingHabits;

public class Cow : Animal
    public Cow() : base(eatingHabits: "herbivore")

If we compare them using the equality (==) operator in the way we did before, we’ll get a false value, as the equality operator works in a strict way.

But we must take into consideration that the is operator will evaluate the possibility of implicit reference conversions when comparing values. For this reason, doing the same comparison as before using an is keyword will inevitably return true:

var bessie = new Cow();

Console.WriteLine(bessie.GetType() == typeof(Animal));
Console.WriteLine(bessie is Animal);

If we run the example code, we’ll see that an is comparison will also return true when an expression returns a type that inherits the type it’s being compared to, as the C# inheritance is a type of implicit reference type conversion.

If you want to know more about implicit conversions, please check out our article on C# Type Conversion. We also have an article on C# Inheritance if you want to know more.

The “As” Operator

The first thing you need to know about the as keyword is that it is a type conversion operator instead of a type comparison one. As such, the cases in which it can be used are pretty different from the is keyword.

The as operator will work for converting either reference types or nullable value types into other types:

var bessie = new Cow();
var bessieAnimal = bessie as Animal;

Console.WriteLine(bessieAnimal is not null);

Since the Cow class that we’ve created in the previous section is a reference type that inherits from the Animal class, we didn’t have problems when trying to make the conversion.

Contrarily, if we try to convert a generic object into a Cow, things will take a different turn:

var imNotACow = new object();
var notBessie = imNotACow as Cow;

Console.WriteLine(notBessie is null ? "The object is null" : "The object is not null");

Running the code above will tell you that the notBessie object is null. But it also tells us something rather interesting. Trying to make an invalid conversion using the as keyword will never throw an exception. This is the main difference between using the as operator and a cast expression.

Considering this fact, using an as conversion is almost the same as using the following expression:

E is T ? (T)(E) : (T)null

The main difference, in this case, is that the as operator does the checking and the casting at the same time. It’s also pretty interesting to see a connection between the two operators we’ve learned about today!

When to Use the As and Is Operators

Okay, now we know what are the as and is operators, but still don’t know much about when to use them, right?

Well, don’t worry about that.

It’s time for us to work on some of the use cases that make the most sense for each of the type-testing operators we’ve learned today.

When we think about the is operator, we see that its main use is comparing types in a readable manner. Also, we may have an application in which we want to make a non-strict type comparison. That’s where the is operator shines the brightest.

But that’s not all!

If you want, you can also check for null values in a more human-friendly way:

static string HumanFriendlyNullCheck(object obj)
    return obj is null ? $"This {typeof(object)} is null" : $"This {typeof(object)} is not null";

As for the as operator, its main real-life use case is when you want to avoid exception handling, since checking for null values will generate much less overhead than throwing exceptions. It’s also simpler to code:

var imNotACow = new object();

var notBessieAs = imNotACow as Cow;
if (notBessieAs is null)
    Console.WriteLine("This verifies that a conversion was not valid using an 'as' operator");

    var notBessieCast = (Cow)imNotACow;
catch (Exception)
    Console.WriteLine("This verifies that a conversion was not valid using a cast expression");

There may be other cases when the operators you’ve learned about today overlap with their counterparts. In these cases, we can follow our personal preferences or the guidelines established by our teams. 


That’s all there is to know about how and when to use the as and is operators in C#! We have learned:

  • How the “is” operator works
  • How the “as” operator works
  • When we should use each one

That’s all for today and we hope to see you again in the next article!