I'm working with the System.Text.Json serializer, and need to provide custom serialization logic for one property of my overall object. That's not the issue, it's working, but I don't understand how. This is the sample provided in the MS docs.
Here's the decompiled code I get with a Go To Definition.
// Summary:
// Gets the list of user-defined converters that were registered.
//
// Returns:
// The list of custom converters.
public IList<Serialization.JsonConverter> Converters { get; }
And, what I think is the original code.
What magick explains this?
CodePudding user response:
It's a collection initializer.
Converters
is a collection. In the following code:
Converters =
{
new DateTimeOffsetJsonConverter()
}
You're not assigning to Converters
itself. Since the type of Converters
is a type that implements IEnumerable
and has an Add
method with the appropriate signature, the compiler simply generates code that calls that Add
method and passes it your DateTimeOffsetJsonConverter
instance. The Converters
property itself does not need a setter because you only need the collection itself.
The fact that it looks like assignment is just a quirk of the grammar.
CodePudding user response:
It's being done through the collection initializers.
Collection initializers let you specify one or more element initializers when you initialize a collection type that implements IEnumerable and has Add with the appropriate signature as an instance method or an extension method. The element initializers can be a simple value, an expression, or an object initializer. By using a collection initializer, you do not have to specify multiple calls; the compiler adds the calls automatically.
While the property itself has only a getter. The instance behind the getter implements IEnumerable<T>
and also has an .Add()
method.
So your code is just syntactic sugar for something like this:
var serializeOptions = new JsonSerializerOptions;
serializeOptions.Converters.Add(new DateTimeOffsetJsonConverter());
CodePudding user response:
It's just a basic Collection initializers.
Collection initializers let you specify one or more element initializers when you initialize a collection type that implements IEnumerable and has Add with the appropriate signature as an instance method or an extension method. The element initializers can be a simple value, an expression, or an object initializer. By using a collection initializer, you do not have to specify multiple calls; the compiler adds the calls automatically.
var names = new List<string> {
"Alice", "Bob", "Curtis", "David"
};
// Equivalent to
var names = new List<string>();
names.Add("Alice");
names.Add("Bob");
names.Add("Curtis");
names.Add("David");
It's possible to use on get only property :
public class Book
{
public IList<string> Names { get; } = new List<string> { "Alice", "Bob" };
}
var book = new Book {
Names = { "Curtis", "David" }
};
// Equivalent to
var book = new Book();
book.Names.Add("Curtis");
book.Names.Add("David");