Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic unboxing of boxed value types

Tags:

c#

.net

I have a generic function that is constrained to struct. My inputs are boxed ("objects"). Is it possible to unbox the value at runtime to avoid having to check for each possible type and do the casts manually?

See the above example:

   public struct MyStruct
    {
        public int Value;
    }

    public void Foo<T>(T test)
        where T : struct
    {
        // do stuff
    }

    public void TestFunc()
    {
        object o = new MyStruct() { Value = 100 }; // o is always a value type

        Foo(o);
    }

In the example, I know that o must be a struct (however, it does not need to be MyStruct ...). Is there a way to call Foo without tons of boilerplate code to check for every possible struct type?

Thank you.

like image 602
mbuchetics Avatar asked May 03 '10 16:05

mbuchetics


People also ask

What is a boxed value?

Boxing is an implicit conversion of a value type to the type object or to any interface type implemented by this value type. Boxing a value type allocates an object instance on the heap and copies the value into the new object.

How can generics avoid boxing and unboxing?

With Generics you avoid doing boxing/unboxing since you are dealing with the parameter type T , which is a natural parameter that the compiler will replace it with the concrete type at compilation time without doing the boxing operation at runtime.

How do generics prevent boxing?

When you use a generic list the compiler outputs specialized code for that value type so that the actual values are stored in the list rather than a reference to objects that contain the values. Therefore no boxing is required.

What is the difference between boxing and unboxing explain with the help of an example?

Boxing is an implicit conversion process. Unboxing is the explicit conversion process. Here, the value stored on the stack copied to the object stored on the heap memory. Here, the object stored on the heap memory copied to the value stored on the stack .


2 Answers

.NET Generics are implemented in a manner that allows value types as a generic type parameter without incurring any boxing/unboxing overhead. Because your're casting to object before calling Foo you don't take advantage of that, in fact you're not even taking advantage of generics at all.

The whole point of using generics in the first place is to replace the "object-idiom". I think you're missing the concept here. Whatever type T happens to be, it is available at run-time and because you constrained it to struct guaranteed to be a struct type.

Your TestFunc could be written like this without problem:

public void TestFunc()
{
    MyStruct o = new MyStruct() { Value = 100 }; // o is always a value type

    Foo<MyStruct>(o);
}

Looking at Foo, it would look like this in your example:

public void Foo<T>(T test)
    where T : struct
{
    T copy = test; // T == MyStruct
}

EDIT:

Ok, since the OP clarified what he wants to call the generic method but doesn't know the type of his struct (it's just object). The easiest way to call your generic method with the correct type parameter is to use a little reflection.

public void TestFunc()
{
    object o = new DateTime();

    MethodInfo method = this.GetType().GetMethod("Foo");
    MethodInfo generic = method.MakeGenericMethod(o.GetType());
    generic.Invoke(this, new object[] {o});


}
public void Foo<T>(T test)
    where T : struct
{
    T copy = test; // T == DateTime
}
like image 113
Johannes Rudolph Avatar answered Oct 20 '22 08:10

Johannes Rudolph


No; you're using object, which is (by definition) not a struct/value type. Why are you intentionally boxing the value in this way?

like image 43
Adam Robinson Avatar answered Oct 20 '22 09:10

Adam Robinson