如何将 an 强制转换(或转换,如果强制转换不可能或不合理)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;
Run Code Online (Sandbox Code Playgroud)
长话短说
您无法将某些内容转换为运行时指定的未知类型。这意味着在您的代码中,您不知道对象的属性或方法是什么,除非您使用更多的反射。在这种情况下,铸造它还有什么意义呢?
有时我们处理直到运行时才知道的类型。但是,除非类型确实根本不重要,否则该对象是无用的,除非我们可以将其转换为代码中指定的某种预定类型,而不是在运行时指定。
在这行代码中:
var val = property.GetValue(obj);
Run Code Online (Sandbox Code Playgroud)
的声明类型val由编译器推断。该类型是object因为这是返回的类型GetValue。对象的实际类型可以是string、int、List<Foo>等等。但你有一个val类型为 的变量object。
如果你能做到这一点:
var val = property.GetValue(obj) as runtimeType;
Run Code Online (Sandbox Code Playgroud)
那么编译时类型是什么val?runTimeType既然是运行时值,它怎么可能有任何值呢?除非您可以调用方法或检查其属性,否则该对象是无用的。但在不知道类型的情况下你无法做到这一点,除非你使用更多的反射。但如果你要这样做,那么铸造它就没有意义了。
在您发布的代码下游的某个地方,您可能希望实际对涉及其方法或属性的对象执行某些操作。这意味着知道您认为它是什么类型并将其转换为该类型。这将是代码中指定的类型,而不是在运行时确定的类型。
例如:
var val = property.GetValue(obj); // I know this is a string
var myString = (string)val;
var findX = myString.IndexOf("X");
Run Code Online (Sandbox Code Playgroud)
我认为这是 astring所以我将其转换为 a string。(那里可能有额外的检查。)现在我已经转换了它,我有一个声明为 type 的变量string,我可以将它用作字符串。(除非它不是string- 那么它将抛出运行时异常。)
这就是强制转换的好处 - 它允许我们将某些内容分配给具有我们指定类型的强类型变量,然后相应地使用它。转换为未知类型不会给我们带来好处。
冒着增加混乱的风险:有人可能会说泛型代表运行时未指定的类型,但这并不完全正确。List<T>没有指定T是什么,但是如果您List<T>以某种方式创建一个 ,您将在代码中指定类型。在绝大多数正常情况下,我们必须了解对象的类型,否则该对象对我们来说毫无用处。