复制对象属性:反射或序列化 - 哪个更快?
我有两个相同类型的对象,需要将属性值从一个对象复制到另一个对象。有两个选项:
使用反射,浏览第一个对象的属性并复制值。
序列化第一个对象并反序列化副本。
两者都适合我的要求,问题是在速度(成本)方面我应该更好地使用哪一个?
示例
class Person
{
public int ID { get; set; }
public string Firsthand { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public decimal Weight { get; set; }
}
需要将属性值从 Person p1
复制到 Person p2
。
对于这个简单的示例 - 哪种方法更快?
更新
对于序列化,我使用此处建议的 ObjectCopier:深度克隆对象
为了反思,我使用以下代码:
foreach (PropertyInfo sourcePropertyInfo in copyFromObject.GetType().GetProperties())
{
PropertyInfo destPropertyInfo = copyToObject.GetType().GetProperty(sourcePropertyInfo.Name);
destPropertyInfo.SetValue(
copyToObject,
sourcePropertyInfo.GetValue(copyFromObject, null),
null);
}
I have two objects of the same type and need to copy property values from one object to another. There are two options:
Use reflection, navigate through the properties of the first object and copy the values.
Serialize the first object and deserialize a copy.
Both work for my requirement, the question is which do I better use in the terms of speed (cost)?
Example
class Person
{
public int ID { get; set; }
public string Firsthand { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public decimal Weight { get; set; }
}
Need to copy property values from Person p1
to Person p2
.
For this simple sample - which method is faster?
Update
For serialization I use the ObjectCopier suggested here: Deep cloning objects
For reflection I use this code:
foreach (PropertyInfo sourcePropertyInfo in copyFromObject.GetType().GetProperties())
{
PropertyInfo destPropertyInfo = copyToObject.GetType().GetProperty(sourcePropertyInfo.Name);
destPropertyInfo.SetValue(
copyToObject,
sourcePropertyInfo.GetValue(copyFromObject, null),
null);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这完全取决于您想要复制的内容以及您计划使用哪种序列化程序。序列化器的问题是,其中一些可能实际上使用反射作为构建对象的底层机制。
编辑#1:据我所知,您的类使用的
BinaryFormatter
确实利用反射来完成其工作。所以问题是,您能否为您的类型编写比 Microsoft 为一般场景编写的更好(更快?)的自定义反射代码?编辑#2:出于好奇,我运行了简单的测试。
BinaryFormatter
与执行浅复制方面的反射。我使用的反射代码可以在这里看到:与您正在使用的
ObjectCopier
类相比,结果是什么?反射的执行速度似乎比序列化代码快 7 倍。然而,这适用于具有公共字段的Person
类。对于属性来说,差异仍然很明显,但速度只快了 2 倍。我认为差异来自于 BinaryFormatter 需要使用流,这会带来额外的开销。但这只是我的假设,可能与事实相去甚远。
我使用的测试程序的源代码可以在此处找到。欢迎任何人指出它的缺陷和可能的问题:-)
旁注
与所有“我想知道...”基准一样,我建议您持保留态度。仅当其性能确实成为问题时才应进行此类优化。
It all depends on what you want to copy, and what kind of serializer you plan to use. Thing with serializers is, some of them might be actually using reflection as underlying mechanism of building objects.
Edit #1: As far as I know,
BinaryFormatter
used by your class does utilize reflection to do its work. So question is, can you write better (faster?) custom reflection code for your types than Microsoft did for general scenario?Edit #2: Out of curiosity, I've run simple test.
BinaryFormatter
vs reflection in terms of performing shallow copy. Reflection code I used can be seen here:What are the results compared to
ObjectCopier
class you're using? Reflection seems to perform 7 times faster than serialization code. This however applies toPerson
class with public fields. For properties, difference is still noticable, but it's only 2 times faster.I assume difference comes from the fact that
BinaryFormatter
needs to use streams, which introduce additional overhead. Yet this is just my assumption, which might be far from facts.Source code for testing program I used can be found here. Anybody is welcome to point flaws and possible problems with it :-)
Sidenote
As with all "I was wondering..." benchmarks, I suggest you take it with a grain of salt. Such optimizations should be only made when their performance actually becomes an issue.
最终,通用序列化器(例如通过
ObjectCopier
的BinaryFormatter
)正在使用反射。他们如何使用它取决于特定的序列化程序,但如果您进行序列化,总是会涉及额外的开销。由于您只需要浅拷贝,因此像 AutoMapper 这样的工具是这里最合适的工具;再次,它使用反射(但我希望它以“正确的方式”执行此操作,即不是通过
GetValue()
/SetValue()
),但它没有没有序列化成本。在这种情况下,序列化就显得大材小用了; AutoMapper 是完全合理的。如果你想要深度克隆,它会变得更加棘手......序列化可能开始变得诱人。我自己可能仍然不会选择 BinaryFormatter,但我对序列化非常挑剔;p
当然,纠正一些通过以下方式执行相同操作的基本反射是微不足道的 :
GetValue()
等,但这会很慢。这里另一个有趣的选项是,您可以使用Expression
API 在运行时创建对象复制器...但是...AutoMapper 在这里完成了您需要的所有操作,因此这似乎是多余的工作。Ultimately, general-purpose serializers (such as
BinaryFormatter
, viaObjectCopier
) are using reflection. How well they use it depends on the specific serializer, but there is always extra overhead involved if you are serializing.Since you only want a shallow copy, a tool like AutoMapper is the most appropriate tool here; again, it is using reflection (but I expect it is doing it "the right way", i.e. not via
GetValue()
/SetValue()
), but it doesn't have the serialization costs.In this scenario, serialization is overkill; AutoMapper is perfectly reasonable. If you wanted deep-clones, it gets trickier... serialization may start being tempting. I still probably wouldn't choose
BinaryFormatter
myself, but I'm very fussy about serialization ;pIt would of course be trivial to right some basic reflection that does the same via
GetValue()
etc, but that would be slow. Another interesting option here is that you can use theExpression
API to create an object copier at runtime.... but... AutoMapper does everything you'd need here, so it seems redundant effort.二进制序列化非常快,我经常使用它来解决此类问题
深度克隆对象
Binary serialization is very fast I use it a lot for this kind of problem
Deep cloning objects
如果您在运行时复制属性,反射就是答案。如果不是在运行时,我会进行序列化。
序列化与反射看一下。
If you are copying the properties during run time, reflection would be the answer. I would go for serialization if its not during run time.
Serialization vs Reflection look at this once.