How can I get the data type of a variable in C#?

Limeni picture Limeni · Jul 24, 2012 · Viewed 193.3k times · Source

How can I find out what data type some variable is holding? (e.g. int, string, char, etc.)

I have something like this now:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Testing
{
    class Program
    {
        static void Main()
        {
            Person someone = new Person();
            someone.setName(22);
            int n = someone.getName();
            Console.WriteLine(n.typeOf());
        }
    }

    class Person
    {
        public int name;

        public void setName(int name)
        {
            this.name = name;
        }

        public int getName()
        {
            return this.name;
        }
    }
}

Answer

phoog picture phoog · Jul 24, 2012

There is an important and subtle issue that none of them addresses directly. There are two ways of considering type in C#: static type and run-time type.

Static type is the type of a variable in your source code. It is therefore a compile-time concept. This is the type that you see in a tooltip when you hover over a variable or property in your development environment.

You can obtain static type by writing helper generic method to let type inference take care of it for you:

   Type GetStaticType<T>(T x) { return typeof(T); }

Run-time type is the type of an object in memory. It is therefore a run-time concept. This is the type returned by the GetType() method.

An object's run-time type is frequently different from the static type of the variable, property, or method that holds or returns it. For example, you can have code like this:

object o = "Some string";

The static type of the variable is object, but at run time, the type of the variable's referent is string. Therefore, the next line will print "System.String" to the console:

Console.WriteLine(o.GetType()); // prints System.String

But, if you hover over the variable o in your development environment, you'll see the type System.Object (or the equivalent object keyword). You also see the same using our helper function from above:

Console.WriteLine(GetStaticType(o)); // prints System.Object

For value-type variables, such as int, double, System.Guid, you know that the run-time type will always be the same as the static type, because value types cannot serve as the base class for another type; the value type is guaranteed to be the most-derived type in its inheritance chain. This is also true for sealed reference types: if the static type is a sealed reference type, the run-time value must either be an instance of that type or null.

Conversely, if the static type of the variable is an abstract type, then it is guaranteed that the static type and the runtime type will be different.

To illustrate that in code:

// int is a value type
int i = 0;
// Prints True for any value of i
Console.WriteLine(i.GetType() == typeof(int));

// string is a sealed reference type
string s = "Foo";
// Prints True for any value of s
Console.WriteLine(s == null || s.GetType() == typeof(string));

// object is an unsealed reference type
object o = new FileInfo("C:\\f.txt");
// Prints False, but could be true for some values of o
Console.WriteLine(o == null || o.GetType() == typeof(object));

// FileSystemInfo is an abstract type
FileSystemInfo fsi = new DirectoryInfo("C:\\");
// Prints False for all non-null values of fsi
Console.WriteLine(fsi == null || fsi.GetType() == typeof(FileSystemInfo));