Do you know what your C# variables contain?

It might sound like a trivial question but there are several ways to analyse a variable and they might give different answers. It’s therefore good to know what the difference in-between them are.

The different tools we’ll go through here are: is, typeof and GetType. To include the complexity of inherited objects we create two classes where one is inheriting from the other one.

class Fruit
  public string color { get; set; }
class Orange : Fruit
  public decimal diameter { get; set; }

Before testing we’ll also create three test variables from the previous two classes:

Fruit anyFruit = new Fruit() { color = "white" };
Fruit orangeFruit = new Orange() { color = "red", diameter = 10.0 };
Orange realOrange = new Orange() { color = "orange", diameter = 8.5 };

The is operator is of great use when testing a variable. It looks at the whole inheritance tree and thus answers if the value can be cast into any of these objects.

Console.WriteLine(orangeFruit is Fruit); // Returns true
Console.WriteLine(orangeFruit is Orange); // Returns true
Console.WriteLine(orangeFruit is Object); // Returns true

Note that orangeFruit is considered to be both an Orange, a Fruit and an Object since all these classes exist in the inheritance tree. As you might have guessed by now the is operator doesn’t look at the reference variable, defined only as a Fruit, but rather at the object stored inside it.

GetType is invoked on an object and is resolved at run time. As the is operator it looks at the content of the variable and returns what’s inside it.

Console.WriteLine(anyFruit.GetType().ToString());  // Writes Fruit
Console.WriteLine(orangeFruit.GetType().ToString());  // Writes Orange
Console.WriteLine(realOrange.GetType().ToString());  // Writes Orange

This can clearly be seen since orangeFruit is written as an Orange.

Generic functions
The typeof method is used when you already know the type. But by using it inside a generic function we can use it as if we didn’t know the type. To test we add this static help function where the type of the input variable is returned.

public static Type GetParameterType<T>(T input)
  return typeof(T);

When using the generic function we can see that the orangeFruit is now considered to be a Fruit and not an Orange. This is because the generic function looks at the type of the reference variable (Fruit) rather than the type of the object stored inside it (Orange).

Console.WriteLine(GetParameterType(anyFruit).ToString()); // Writes Fruit
Console.WriteLine(GetParameterType(orangeFruit).ToString()); // Writes Fruit
Console.WriteLine(GetParameterType(realOrange).ToString()); // Writes Orange

Null values
When a variable contains a null value some complications occur because GetType can’t be called on a null-reference object. And while is works with null values, it might not give you the answer you’d expect.

Orange realOrange = null;
Console.WriteLine(realOrange is Orange); // Returns false

This might feel a bit inconsistent but it has to do with the fact that the is operator looks at the content and since null means absence of content it has to return false. The variable is declared with the possibility to contain an Orange (or a specialization of an Orange), not necessarily that it will contain one.

As mentioned earlier, the generic help function looks at the reference variable and therefore it doesn’t have any problems with null values. This can be seen in this final example:

Orange realOrange = null;
Console.WriteLine(GetParameterType(realOrange) == typeof(Orange)); // true, because orangeFruit is of type Orange

But it’s important to remember that if you were to check the orangeFruit variable you’d only get the generalized type (Fruit) and not the specialized one (Orange) when using the generic function!

More reading
If you want to read more about the is operator you can continue here.