Reputation: 6224
How can I cast (or convert, if cast not possible or reasonable) an object
into its runtime type? I can get runtimeType
using reflection, but can't figure out how to get List<string>
using property.GetValue
- I know that I could explicitly do as List<String>
but this is for a sort-of soft-code engine where the types are not known until runtime.
Any help is appreciated - thanks! (but looking for code solutions please, not "you shouldn't do it this way..." answers)
// trimmed-down example class
class Bus { public List<string> Passengers {get;set;} }
// create new instance of class
var obj = new Bus();
// get property value using reflection
var listPropertyName = "Passengers";
var property = GetType(obj).GetProperty($"{listPropertyName}");
var runtimeType = property.PropertyType;
// returns object, but I want List<string> instead
// (or whatever it is; could be different types like T, List<T>, etc.)
var val = property.GetValue(obj);
// doesn't work (assigns null), expects compile-time type
var val = property.GetValue(obj) as runtimeType;
Upvotes: 3
Views: 6420
Reputation: 29207
TL;DR
You can't cast something to an unknown type specified at runtime. That would mean that within your code, you don't know what the object's properties or methods are unless you use even more reflection. In that case what would be the point of casting it?
Sometimes we deal with types that aren't known until runtime. But unless the type really doesn't matter at all, the object is useless unless we can cast it to some predetermined type that is specified in our code, not at runtime.
In this line of code:
var val = property.GetValue(obj);
the declared type of val
is inferred by the compiler. That type is object
because that's the type that GetValue
returns. The actual type of the object could be string
, int
, List<Foo>
, whatever. But you've got a variable val
of type object
.
If you could do this:
var val = property.GetValue(obj) as runtimeType;
Then what would the compile-time type of val
be? How can it have any, since runTimeType
is a runtime value? The object is useless unless you can call methods or inspect its properties. But you can't do that without knowing the type, unless you use more reflection. But if your're going to do that then there's no point in casting it.
Somewhere downstream from the code you've posted you'll presumably want to actually do something with the object that involves its methods or properties. That means knowing what type you think it is and casting it as that type. That would be a type specified in your code, not something determined at runtime.
For example:
var val = property.GetValue(obj); // I know this is a string
var myString = (string)val;
var findX = myString.IndexOf("X");
I think it's a string
so I cast it as a string
. (There could be additional checks in there.) Now that I've cast it, I've got a variable that's declared as type string
, and I can use it as a string. (Unless it wasn't a string
- then it will throw a runtime exception.)
That's the benefit of casting - it allows us to assign something to a strongly-typed variable with a type we specify and then use it accordingly. Casting to an unknown type wouldn't benefit us.
At the risk of adding confusion: Someone could say that generics represent types unspecified at runtime, but that's not exactly true. List<T>
doesn't specify what T
is, but if you create a List<T>
, somehow, somewhere you're going to specify the type in your code. In the vast majority of normal scenarios we have to know something about the type of an object or else the object is useless to us.
Upvotes: 6