views:

70

answers:

3

I am working in c# with .net 2.0 (i know its old)

Here is my setup:

struct propertyType
{
          System.type type;
}

public class DataProperties
{
        private Dictionary<propertyType, object> properties;

        public void setProperty(propertyType key, object value)
        {
          if(value.getType == key.type) //make sure they are adding valid data
                properties.add(key, value);
        }

        public T getProperty<T> (propertyType key)
       { 
           return (T)properties[key];
       }
}

Then in my class that needs to pull properties it would look like

//this would be declared somewhere else for use by multiple classes. 
   //but for example sake its here
propertyType hash;
   hash.type = typeof(byte[]);

byte[] hashCode = DataSet.properties.GetProperty<hash.type>(hash);

Now the last line is the one that doesnt work, but I'd like to work. I think the problem is that it doesnt like having a variable as the Type. In actual use there will be many different PropertyType objects so I want a way to get the properties out and cast to the correct type easily.

Does anyone know if it is for sure that the variable as the type is the problem. But at compile time it will know what hash.type is so its not that its an unknown value at compile time.

+4  A: 

No, it is an unknown value at compile-time, as far as the compiler is concerned. Just because you've set it in the previous line doesn't mean the compiler really knows the value.

You simply can't use variables to specify type arguments in C# generics, other than with reflection. A type argument has to be the name of a type or another type parameter - it can't be an expression which evaluates to a System.Type.

Jon Skeet
+2  A: 

the problem is that it doesnt like having a variable as the Type

That's right. There's no way to do this that keeps compile-time safety. It's possible to use reflection to call the getProperty method with a generic type that you only know at run time, but generics don't gain you anything in this case.

Since you're only using generics to do a type cast, why not add an overload to getProperty that's not generic and returns object?

Tim Robinson
Hey, I was trying to come up with a way that didnt involve returning an object and then casting it in my main class. The properties are going to be getting pulled out often and I want to call to get it ot be as simple as possible. If i have to also do casting/boxing in the getproperty line then the line begins to look ugly.
Without Me It Just Aweso
Sure, that makes sense. But if you don't know the generic type at compile time, you can't avoid the cast.
Tim Robinson
See I think thats where I'm getting confused. Because I set Hash.type so when i used hash.type it is technically a known value at compile time. I guess I'm confused why the compiler cant see what the current value is. Is it because its afraid somewhere during execution the value would change? If i set the .type to be a const do you think that would help? (i'm speculating right now as i'm not near my code to try it at the moment)
Without Me It Just Aweso
+1  A: 

As Jon Skeet and others have said, this cannot be done without reflection. So, here's some reflection code that should get you on the right track:

Type myGenericParam = typeof(byte[]);
MethodInfo method = typeof(DataProperties).GetMethod("getProperty").MakeGenericMethod(new[] { myGenericParam });

DataProperties foo = new DataProperties();
byte[] result = (byte[])method.Invoke(foo, new[] { /*parameters go here in order */ });
Nathan Taylor