It basically boils down to type instantiation and the ObjectCreationHandling
setting. There are three settings for ObjectCreationHandling
Auto 0 Reuse existing objects, create new objects when needed.
Reuse 1 Only reuse existing objects.
Replace 2 Always create new objects.
The default is auto
(Line 44).
Auto is only overwritten after a series of checks which determine if the current type has a TypeInitializer
which is null. At that point it checks if there is a parameterless constructor.
///
/// Create a factory function that can be used to create instances of a JsonConverter described by the
/// argument type.
/// The returned function can then be used to either invoke the converter's default ctor, or any
/// parameterized constructors by way of an object array.
///
Essentially it acts like this (what it looks like is about 1500 lines of code in 6 classes).
ObjectCreationHandling och = ObjectCreationHandling.Auto;
if( typeInitializer == null )
{
if( parameterlessConstructor )
{
och = ObjectCreationHandling.Reuse;
}
else
{
och = ObjectCreationHandling.Replace;
}
}
This setting is a part of the JsonSerializerSettings which are composed inside of the visitor pattern constructor for DeserializeObject. As shown above, each setting has a different function.
Getting back to List, Collection, and ReadOnlyCollection, we will look at the set of conditional statements for each.
List
testObj.List.GetType().TypeInitializer == null
is false. As a result, List
receives the default ObjectCreationHandling.Auto and the instantiated List for the testObj instance is used during deserialization, as well as a new List being instantiated with the serialized
string.
testObj.List: ABC,DEF,Goodbye,AOL
Collection
testObj.Collection.GetType().TypeInitializer == null
is true indicating there was no reflected type initializer available, so we go to the next condition which is to check if there is a parameterless constructor. testObj.Collection.GetType().GetConstructor(Type.EmptyTypes) == null
is false. As a result Collection
receives the value of ObjectCreationHandling.Reuse (only reuse existing objects). The instantiated instance for Collection is used from testObj, but the serialized
string is not able to be instantiated.
testObj.Collection: ABC,DEF
ReadOnlyCollection
testObj.ReadOnlyCollection.GetType().TypeInitializer == null
is true indicating there was no reflected type initializer available, so we go to the next condition which is to check if there is a parameterless constructor. testObj.ReadOnlyCollection.GetType().GetConstructor(Type.EmptyTypes) == null
is also true. As a result ReadOnlyCollection recieves the value of ObjectCreationHandling.Replace (always create new objects). Only the instantiated value from the serialized
string is used.
testObj.ReadOnlyCollection: Goodbye,AOL