使用反射设置 C# 结构/类字段时是不是可以避免装箱?

Posted

技术标签:

【中文标题】使用反射设置 C# 结构/类字段时是不是可以避免装箱?【英文标题】:Is it possible to avoid boxing when setting C# struct/class fields using reflection?使用反射设置 C# 结构/类字段时是否可以避免装箱? 【发布时间】:2015-12-02 15:14:50 【问题描述】:

假设我有一个原始值,我需要使用反射将其分配给某个字段。我确定该字段具有相同的原始值类型。

是否可以在不装箱的情况下以某种方式设置此值?

void SetFloat(object o, string name, float val)

  var type = o.GetType();
  var fld = type.GetField(name);
  fld.SetValue(o, val /*boxing happens here*/);

附:这实际上与延迟无关,而与可能的 GC 压力有关。我正在使用 Unity3D,它使用非常旧的 Mono 版本,而后者又使用了非常非最佳的 GC 实现。每个额外的内存分配都很重要:(

P.P.S 我正在构建自己的基于 C# 的解释器,避免反射似乎几乎是不可能的。

【问题讨论】:

据我所知,不,FieldInfo.SetValue() 仅具有接受 object newValue 的重载,因此您传递的任何值类型都会被装箱。 使用反射的性能比装箱值的工作量要数量级。将值装箱非常快,与正常设置字段与使用反射之间的差异相比,几乎快得无法估量。这就像在您决定从纽约步行到洛杉矶而不是乘坐飞机时,询问是否有办法避免系鞋带。 嗯,这实际上与速度无关,而与可能的 GC 压力有关。我正在使用 Unity,它使用非常旧的 Mono 版本,而后者又使用了非常非最佳的 GC 实现。每个额外的分配都很重要:( @pachanga 为避免装箱而尝试做的任何事情无疑都需要做的不仅仅是分配一个简单的变量,因此会增加 GC压力,而不是删除它。 您也许可以获取 setter 方法并将其转换为委托类型。然后正常调用该委托。 【参考方案1】:

field.SetValueDirect 可以,但缺点是你不能使用 IL2CPP,因为它不支持。

【讨论】:

以上是关于使用反射设置 C# 结构/类字段时是不是可以避免装箱?的主要内容,如果未能解决你的问题,请参考以下文章

C# 怎么判断一个字符串是不是是一个类的字段属性

C# 反射 设置字段值无效的解决办法

.Net C# 反射,了解只需3分钟

C#高阶-反射

如何使用反射设置另一个结构的字段之一的结构字段值?

在 Java 中,是不是可以在运行时使用反射将成员变量添加到类中?