views:

133

answers:

1

I was reading a question on making a generic property, but I'm a little confused by the last example from the first answer (I've included the relevant code below):

You have to know the type at compile time. If you don't know the type at compile time then you must be storing it in an object, in which case you can add the following property to the Foo class:

public object ConvertedValue {
    get {
        return Convert.ChangeType(Value, Type);
    }
}

That's seems strange: it's converting the value to the specified type, but it's returning it as an object when the value was stored as an object. Doesn't the returned object still require un-boxing? If it does, then why bother with the conversion of the type?

I'm also trying to make a generic property whose type will be determined at run time:

public class Foo
{
    object Value {get;set;}
    Type ValType{get;set;}
    Foo(object value, Type type)
    { Value = value; ValType = type; }

    // I need a property that is actually
    // returned as the specified value type...
    public object ConvertedValue {
        get {
            return Convert.ChangeType(Value, ValType);
        }
    }
}

Is it possible to make a generic property? Does the return property still require unboxing after it's accessed?

Note: I don't want to make Foo generic because I want Foo to contain values of different types and I want to put various Foos into a collection. In other words, I want to have a collection that holds different types of objects.

+2  A: 

Convert.ChangeType() decides on the type at run time. The parameter you give can be calculated at run time and can be something the compiler can't know on compilation.

This is why it must return a generic object and not a specific type.

It still converts the type - for example from int to double. The compilation time type is object but the run time type changes. If you run GetType() on that object you will get the actual run time type.

When you convert a value type to a reference type you get boxing and the other way around you get un-boxing - so this depends on the types you use.

brickner
OK, but I still have to cast the object returned from the ConvertedValue property to the run time type... is it possible to directly return the object in its run time type the same way as a generic?
Lirik
@Lirik, you have to cast it so the compile time will be the type you want. The run time type was "cast" (actually converted) by the ChangeType() method. The problem with using generics here is that you can't limit your generic type to int/short/byte/double... You have to use a more general limits (using where keyword) and this doesn't allow you to do what you want. My suggestion is using overloads or C#4.0 dynamic.
brickner
@brickner, I'm using 3.5 and I can't get C#4.0 yet... overloads are not suitable, because I'm passing in Func delegates. There are just way too many possible declarations of Func delegates for me to actually write overloads (and there might be even more in the future). I guess I'll have to to the casting on the "client" side of the Foo class.
Lirik