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

Answers


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
}

Defining a struct actually defines two types: a value type, and a class type which derives from System.ValueType. If a request is made to create a variable, parameter, field, or array (collectively, 'storage location') of a type which derives from System.ValueType, the system will instead create a storage location which will store the object's fields rather than storing a reference to an object in which those fields appear. On the other hand, if a request is made to create an instance of a type deriving from System.ValueType, the system will create an object instance of a class which derives from System.ValueType.

This may be demonstrated by creating a struct which implements IValue:

interface IValue {int value {get; set;}};
struct ValueStruct : IValue
{
  public int value {get; set;}};
}

with generic test routine and code to wrap it:

static void Test<T>(T it) where T:IValue
{
  T duplicate = it;
  it.value += 1;
  duplicate.value += 10;
  Console.WriteLine(it.value.ToString());
}
static void Test()
{
  ValueStruct v1 = new ValueStruct();
  v1.value = 9;
  IValue v2 = v1;
  Test<ValueStruct>(v1); 
  Test<ValueStruct>(v1); 
  Test<IValue>(v1); 
  Test<IValue>(v1); 
  Test<IValue>(v2);
  Test<IValue>(v2);
}

Note that in every case, calling GetType on the parameter passed to Test would yield ValueStruct, which will report itself as a value type. Nonetheless, the passed-in item will only be a "real" value type on the first two calls. On the third and fourth calls, it will really be a class type, as demonstrated by the fact that a change to duplicate will affect it. And on the fifth and sixth calls, the change will be propagated back to v2, so the second call will "see" it.


static class Metadata<T>
{
    static public readonly Type Type = typeof(T);
    static public readonly bool IsValueType = Metadata<T>.Type.IsValueType;
}

//fast test if T is ValueType
if(Metadata<T>.IsValueType) //only read static readonly field!
{
    //...
}

There are two rules:

1-All Classes are reference types such as Object and String, so it's supported by .NET Framework classes.

2-All structures are value types such as bool and char, even though it contain reference member, so it's supported by .NET Framework structures.

Simply right click on any type and Go To Definition if it's a Class so that means it a reference type else if it's a Struct so that means it's a value type :)


Need Your Help

Search multi-dimensional array JavaScript

javascript jquery

I have an array which looks like this :

How to echo a default value if value not set blade

laravel laravel-4 laravel-5 blade templating

I would like to know what would be the best way to display a default value if the given value is not set. I have the following in a blade file (I can not guaranty that the key is set, it depends on a