Most efficient way to check if an object is a value type

WARNING: THIS CODE SUCKS, SEE ANTHONY'S COMMENTS

Which is faster?

1.

  public bool IsValueType<T>(T obj){
       return obj is ValueType;
  }

2.

  public bool IsValueType<T>(T obj){
       return obj == null ? false : obj.GetType().IsValueType;
  } 

3.

  public bool IsValueType<T>(T obj){
       return default(T) != null;
  }

4.Something else


You aren't really testing an object - you want to test the type. To call those, the caller must know the type, but... meh. Given a signature <T>(T obj) the only sane answer is:

public bool IsValueType<T>() {
    return typeof(T).IsValueType;
}

or if we want to use an example object for type inference purposes:

public bool IsValueType<T>(T obj) {
    return typeof(T).IsValueType;
}

this doesn't need boxing (GetType() is boxing), and doesn't have problems with Nullable<T>. A more interesting case is when you are passing object...

 public bool IsValueType(object obj);

here, we already have massive problems with null, since that could be an empty Nullable<T> (a struct) or a class. But A reasonable attempt would be:

public bool IsValueType(object obj) {
    return obj != null && obj.GetType().IsValueType;
}

but note that it is incorrect (and unfixable) for empty Nullable<T>s. Here it becomes pointless to worry about boxing as we are already boxed.


My first answer would be to write a simple test and find out for yourself.

My second answer (without any testing on my part, of course) would be option 1. It is the simplest check. The second method involves two separate checks while the third involves creating a default instance of a type.

You should also consider readability. The framework already gives you the ability to have the following in your code:

if(someObj is ValueType)
{
    // Do some work
}

Why even bother creating a method that would simply turn the above statement into (assuming you made your method static and allowed the compiler to infer the generic type):

if(IsValueType(someObj))
{
    // Do some work
}