gpt4 book ai didi

具有数组参数和任意元素类型的 C# FieldInfo.SetValue

转载 作者:行者123 更新时间:2023-11-30 21:01:54 26 4
gpt4 key购买 nike

我正在尝试像这样使用反射来设置数组字段:

FieldInfo field = ...
A[] someArray = GetElementsInSomeWay();
field.SetValue(this, someArray);

该字段的类型为 B[]B 继承自 A 并且 B 的确切类型在编译时未知。GetElementsInSomeWay() 返回 A[] 但里面的真实元素都是 B 的。 GetElementsInSomeWay() 是一个库方法,无法更改。

我最多只能用 System.Type type = field.FieldType.GetElementType() 获取 B。但是我无法将数组转换为所需的类型,例如someArray as type[] 因为 [] 在声明数组类型之前需要一个确切的类型。还是我在这里遗漏了什么?如果类型在运行时使用 System.Type 变量已知,我可以声明某种类型的数组吗?

直接执行会产生以下错误(这里AUnityEngine.ComponentBAbilityResult 它也可以是几十个其他类之一,所有类都继承(可能通过一个长的继承链)UnityEngine.Component:

ArgumentException: Object type UnityEngine.Component[] cannot be converted to target type: AbilityResult[]
Parameter name: val
System.Reflection.MonoField.SetValue (System.Object obj, System.Object val, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture) (at /Applications/buildAgent/work/3df08680c6f85295/mcs/class/corlib/System.Reflection/MonoField.cs:133)
System.Reflection.FieldInfo.SetValue (System.Object obj, System.Object value) (at /Applications/buildAgent/work/3df08680c6f85295/mcs/class/corlib/System.Reflection/FieldInfo.cs:150)

最佳答案

我认为您需要更好地理解数组的方差。类似 object[] 的数组和 string[]在泛型 (.NET 2) 之前很久就已经出现在 .NET 1 中。否则它们可能被称为 Array<object>Array<string> .

现在,我们都知道任何 string是一个 object .如果这个事实暗示,对于一些“ build ”Xxx , 任何Xxx<string>是一个 Xxx<object> , 然后我们称之为 covaraince .从 .NET 4 开始,一些泛型接口(interface)和泛型委托(delegate)类型可以是协变的,并且用 out 标记。他们定义中的关键字,如

public interface IEnumerable<out T>
{
// ...
}

如果关系在“应用”时颠倒了 Xxx<> ,那么这就是所谓的逆变。所以“string is object”与逆变变为“Xxx<object> is Xxx<string>”。

现在,回到数组。这里的自然问题是:数组是协变的还是逆变的,或者两者都不是(“不变”)?由于您可以读取和写入数组中的每个“单元格”,因此它们不能完全协变或逆变。但是试试这段代码:

string[] arr1 = { "these", "are", "strings", };
object[] arr2 = arr1; // works! covariance!
var runtimeType = arr2.GetType(); // System.String[]

所以一个T[]在 .NET 中是协变的。但是我不是说我可以写(比如 in 而不是 out )到数组吗?那么,如果我继续这样怎么办:

arr2[0] = new object();

我正在尝试输入 object不是 string进入第零个插槽。上面的行必须编译( arr2 的编译时类型是 object[] )。但它也必须引发异常运行时。这就是数组和协方差的问题。

那么逆变呢?试试这个:

object[] arrA = { new object(), DateTime.Now, "hello", };
string[] arrB = arrA; // won't compile, no cotravariance

object[] 进行显式转换至 string[]仍然无法在运行时工作。

现在,您的问题的答案是:您正在尝试对数组应用逆变。 AbilityResultComponent ,但这并不暗示Component[]AbilityResult[] .谁写了 GetElementsInSomeWay()方法,选择创建一个 new Component[] .即使他放入其中的所有组件都是 AbilityResult ,仍然没有逆变。 GetElementsInSomeWay()的作者可以选择制作new AbilityResult[]反而。他仍然可以返回类型 Component[]因为 .NET 数组的协方差。

要学习的教训:数组的真实类型(.GetType() 显示的运行时类型)不会仅仅因为您强制转换而改变。 .NET 确实允许协变(类型为 Component[] 的变量可能包含一个实际类型为 AbilityResult[] 的对象)。最后,.NET 不允许允许逆变(类型 AbilityResult[] 的变量从不持有对实际类型 Component[] 对象的引用)。

希望这对您有所帮助。否则,我的回答应该会为您提供一些术语,您可以通过谷歌搜索找到比我的更好的解释。

关于具有数组参数和任意元素类型的 C# FieldInfo.SetValue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13790527/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com