如何将object
转换(或转换,如果不可能或合理转换)为其运行时类型?我可以使用反射来获取runtimeType
,但无法弄清楚如何使用List<string>
来获取property.GetValue
-我知道我可以显式地执行as List<String>
,但这是一种-类型的软代码引擎,直到运行时才知道类型。
感谢您的帮助-谢谢! (但是请寻找代码解决方案,而不是“您不应该这样……”答案)
// 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;
答案 0 :(得分:3)
TL; DR
您不能将某些内容转换为运行时指定的未知类型。这意味着在代码中,除非使用更多的反射,否则您将不知道对象的属性或方法是什么。在那种情况下,铸造它的目的是什么?
有时我们处理直到运行时才知道的类型。但是除非类型真的没有关系,否则对象是无用的,除非我们可以将其强制转换为代码中指定的某个预定类型,而不是在运行时。
在这一行代码中:
var val = property.GetValue(obj);
val
的声明类型由编译器推断。该类型为object
,因为这是GetValue
返回的类型。对象的实际类型可以是string
,int
,List<Foo>
,无论如何。但是您拥有类型val
的变量object
。
如果您可以这样做:
var val = property.GetValue(obj) as runtimeType;
那么val
的编译时类型是什么?由于runTimeType
是运行时值,它怎么有呢?该对象是无用的,除非您可以调用方法或检查其属性。但是除非知道更多类型,否则您将无法做到这一点。但是,如果您要这样做,则强制转换是没有意义的。
在您发布的代码的下游,您可能想对包含其方法或属性的对象进行实际操作。这意味着知道您认为是什么类型,并将其强制转换为该类型。那将是您的代码中指定的类型,而不是在运行时确定的类型。
例如:
var val = property.GetValue(obj); // I know this is a string
var myString = (string)val;
var findX = myString.IndexOf("X");
我认为它是string
,所以我将其转换为string
。 (在那里可能会有其他检查。)现在,我已经对其进行了强制转换,有了一个声明为类型string
的变量,并且可以将其用作字符串。 (除非它不是string
,否则它将引发运行时异常。)
这是强制转换的好处-它允许我们将某些东西分配给具有我们指定类型的强类型变量,然后相应地使用它。强制转换为未知类型不会使我们受益。
冒着增加混乱的风险:有人可能会说泛型表示运行时未指定的类型,但这并非完全正确。 List<T>
并未指定T
是什么,但是如果您创建List<T>
,则将以某种方式在代码中指定类型。在绝大多数正常情况下,我们必须了解某个对象的类型,否则该对象对我们毫无用处。