3

I have a type like this:

public class TypeValue
{
    public Type Type { get; private set; }
    public object Value { get; private set; }
}

so I can do something like:

TypeValue tv = ...
int count = (tv.Type) tv.Value;

but the compiler is giving me this error:

The type or namespace name 'tv' could not be found (are you missing a using directive or an assembly reference?)

How do I achieve this?

Joan Venge
  • 315,713
  • 212
  • 479
  • 689
  • Thanks but why? Type isn't a keyword, right? – Joan Venge Feb 11 '11 at 23:34
  • In your example you know that 'count' is an int because you just declared it. – Ed S. Feb 11 '11 at 23:41
  • Agreed there is that. I have to think about this but I might not need this kind of cast then. Although I am still surprised I couldn't do the above thing. For instance, how can I store "the int" so it could be placed in code like above? I guess that can't be done. Because if "(type) value" was using actual System.Type values then it would still work because it would be known at compile time, no? – Joan Venge Feb 11 '11 at 23:52

4 Answers4

3

No. How would the compiler be able to determine what type "Type" refers to at compile time? A "type" object is not the same thing as the name of a type that is used when performing a cast. For example, this doesn't work either:

// "typeof" returns a "Type" object.
string foo = (typeof(string))SomeObj;

You won't be able to use a static cast, but you can be sneaky and do this using reflection at runtime.

Community
  • 1
  • 1
Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • Then how can I do runtime casts? – Joan Venge Feb 11 '11 at 23:32
  • 1
    Actually, that was a bad example. Posted a different one. – Ed S. Feb 11 '11 at 23:37
  • Using C# `dynamic` might also be an option, depending on what Joan is trying to do with the cast value. – itowlson Feb 11 '11 at 23:44
  • If I use dynamic, do I just change the object Value to dynamic Value? – Joan Venge Feb 11 '11 at 23:47
  • Yes. You can then return it into whatever type you want... at the risk of returning it into the wrong type and getting a runtime exception. – itowlson Feb 11 '11 at 23:58
  • So essentially does it try to do the same cast like: (int) tv.Value? Also you could still catch the exception, right? – Joan Venge Feb 12 '11 at 00:13
  • 1
    Yes. It looks at the LHS: thus, `string text = tv.Value;` would attempt to cast to string, and `int count = tv.Value;` would attempt to cast to int. And you can catch RuntimeBinderException to handle where tv.Value wasn't the right type. Note this is a simple cast: it will NOT attempt to e.g. parse a string into an integer, or call ToString() if the target is a string, nor will it consider conversion operators. – itowlson Feb 12 '11 at 00:28
3

Assignment you displayed cannot be done way you want. Types of objects on either sides of assignment operator must be equal (or right-hand object must be of type inheriting left-hand object type).

So, you cant do

Type1 obj1 = new Type1();
Type type = typeof(Type1);
Type2 obj2 = (type)obj1;

You could achieve functionality you want by making your class generic, or having a generic method for getting value. E.g.

public class TypeValue
{
    public Type Type { get; private set; }
    public object Value { get; set; }

    public T GetValueAs<T>()
    {
        if (Value == null)
            return default(T);
        return (T)Value;
    }
}

TypeValue a = new TypeValue();
a.Value = 1;
int b = a.GetValueAs<int>();

or even better

public class TypeValue<T>
{
    public Type Type { get { return typeof(T); } }
    public T Value { get; set; }
}

TypeValue<int> a = new TypeValue<int>();
a.Value = 1;
int b = a.Value;
Type c = a.Type;
Nikola Radosavljević
  • 6,871
  • 32
  • 44
  • +1 for second solution. First one is not a solution, he doesn't have type `int` with him. He needs to get it dynamically from TypeValue.Type property. – nawfal Jan 17 '14 at 13:16
1

You should just do:

TypeValue tv = ...
int count = (int) tv.Value;

See, in the case where you know the type at compile-time (in this case you know that count is an int), then there's no point referring to tv.Type anyway. This helps illustrate why this doesn't make logical sense and thus is not possible.

tenfour
  • 36,141
  • 15
  • 83
  • 142
  • The point is that the type of `count` is *always* known, even if the type of `tv.Value` is not. Thus you can use a static cast. If you do not even know the type of `count`, then this entire situation doesn't apply as you cannot really do anything with the object anyway except pass it to someone else... who will eventually do a cast when the type is assumed. – tenfour Feb 11 '11 at 23:43
  • You are right. I was just trying to save the Type value so it might be used the way I posted above, but I guess there is no point for this. – Joan Venge Feb 11 '11 at 23:46
1

It's impossible to get a strongly-typed variable from System.Type and System.Object. Sometimes you can make your class generic like this:

public class TypeValue<T> 
{     
    public T Value { get; private set; } 
} 
Cheng Chen
  • 42,509
  • 16
  • 113
  • 174