Copy object properties: reflection or serialization - which is faster?

I have two objects of the same type and you need to copy the property values ​​from one object to another. There are two options:

  • Use reflection, go through the properties of the first object and copy the values.

  • Serialize the first object and deserialize the copy.

Both work for my requirement, the question is, what should I use in 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; } } 

You must copy the property values ​​from Person p1 to Person p2 .

For this simple example, 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); } 
+8
c # serialization deserialization deep-copy shallow-copy
source share
5 answers

It all depends on what you want to copy and what type of serializer you plan to use. The thing with serializers is that some of them can actually use reflection as the main mechanism for constructing objects.

Edit # 1: As far as I know, the BinaryFormatter used by your class uses reflection to do its job. So the question is, can you write better (faster?) Custom reflection code for your types than Microsoft for the general script?

Edit # 2: Out of curiosity, I checked a simple test. BinaryFormatter against reflection in terms of performing a shallow copy. The reflection code I used can be seen here:

 var newPerson = Activator.CreateInstance<Person>(); var fields = newPerson.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (var field in fields) { var value = field.GetValue(person); field.SetValue(newPerson, value); } 

What are the results compared to the ObjectCopier class you are using? Reflection seems to be 7 times faster than serialization code. However, this applies to the Person class with public fields . For properties, the difference is still noticeable, but it is only 2 times faster.

I assume that the difference is due to the fact that BinaryFormatter needs to use streams that enter additional overhead. But this is only my assumption, which may be far from the facts.

The source code for the testing program I used can be found here . Anyone can point out flaws and possible problems :-)


Sidenote
As in all tests "I wondered ...", I suggest you take it with salt. Such optimization should be done only when their performance really becomes a problem.

+10
source share

Ultimately, universal serializers (like BinaryFormatter , via ObjectCopier ) use reflection . How much they are used depends on the particular serializer, but serialization always incurs additional overhead.

Since you only need a small copy, a tool such as AutoMapper is the most suitable tool here; again, it uses reflection (but I expect it to do this the “right way”, that is, not through GetValue() / SetValue() ), but it does not have serialization.

In this scenario, serialization is full; AutoMapper is quite intelligent. If you need deep clones, it gets harder ... serialization can start seductively. I still probably would not have chosen BinaryFormatter myself, but I'm very fussy about serialization, p

Of course, it would be trivial to rule over some basic reflection that does the same through GetValue() , etc., but it will be slow. Another interesting option is that you can use the Expression API to create a copy of the object at runtime .... but ... AutoMapper does everything you need here, so it seems like an extra effort.

+7
source share

Binary serialization is very fast, I use a lot for this problem

Deep cloning objects

0
source share

If you copy properties at run time, reflection will be the answer. I would go for serialization if it is not at runtime. Serialization vs Reflection look at it once.

0
source share
 void Copy(object copyToObject, object copyFromObject) { BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; FieldInfo[] fields = copyFromObject.GetType().GetFields(flags); for (int i = 0; i < fields.Length; ++i) { BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; FieldInfo field = copyFromObject.GetType().GetField(fields[i].Name, bindFlags); FieldInfo toField = copyToObject.GetType().GetField(fields[i].Name, bindFlags); if(field != null) { toField.SetValue(copyToObject, field.GetValue(copyFromObject)); } } } 
0
source share

All Articles