简体   繁体   中英

Convert.ChangeType to System.Type

I have a System.Type stored in a variable. I wish to Change an object's type to this type.

I have the following code, but cannot get the Type to change to the type.

Ideally I'd like: var intTest3 =(MyType)Convert.ChangeType(test, MyType); to return an int, when : MyType is a System.Int32

Here's my working so far - where am I going wrong?

        // object to cast to int
        object test = 1;

        // INT32 type
        Type MyType = typeof(System.Int32);

        // explicit type int WORKS
        var intTest = (int)Convert.ChangeType(test, typeof(Int32));


        // explicit type to int WORKS
        var intTest2 = (int)Convert.ChangeType(test, MyType);

        // explicit type to int WORKS - but as object
        object intTest3 = Convert.ChangeType(test, MyType);


        // cast to my type DOESNT WORK
        var intTest3 =(MyType)Convert.ChangeType(test, MyType);

Thank you!

It's not supposed to. MyType isn't a "type" as far as C# is concerned, it's a variable of type "Type". The "type" of "MyType" is "Type", but you can't cast 1 to "Type".

In this situation, you've entered "reflection-land" but you're really trying to find a way out. I'm sorry, but there's no way to get back to strongly-typed-land from this sort of situation.

One workaround you could try to do however, is to move that last line into another generic method, and then invoke the method generically:

public static void LeaveReflectionLand<T>(object value)
{
     T newItem = (T)value;
}

Then from outside, you'd have to do something like this:

this.GetType().GetMethod("LeaveReflectionLand", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(MyType).Invoke(null, test);

But of course, that's a huge and scary workaround. Check Jon Skeet's answer... I think it put things clearly.

The long and the short of it is, as MyType is an instance of the class Type, it could represent any type at all. It's a variable just like int, as far as the compiler is concerned. It's not a proper "type" in and of itself, it's a variable that "describes" a type. Because it's a variable that describes a type, there's no way, at compile time, for the compiler to know the actual type described by MyType, so this sort of thing isn't allowed.

It's not unlike doing something like this:

int test = 1;
int MyType = 2;
int anotherTest = (MyType)test;

Obviously, you can't do this. MyType is a variable of type Int32. The same is true when the type of MyType is Type, only in that situation MyType is a variable of type Type.

The key to understanding this is the difference between the "Type class" and the "compiler type".

I hope this helps. It's not the easiest thing to explain in words.

This isn't really about Convert.ChangeType - it's about casting. The type you're casting to has to be known at compile time , although it could be a generic type. In this case, as far as the compiler is concerned MyType could refer to any type. It doesn't "know" that it will definitely have the value typeof(int) , so it won't just emit a cast to int .

In this case, what would you expect the compile-time type of intTest3 to be?

What's the bigger picture here? What are you really trying to do? How would you want to use the value of intTest3 ?

MyType is a Type , which is a variable containing the definition information of a struct / class. Casting by putting the type in brackets eg (int)value; requires the item in the brackets to be an actual class or struct, not a variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM