0

Why or how does the following code work:

var mail = new MailMessage
{
    To = { "hello@abc.com" }
};

given that both MailMessage.To is a readonly property, and it is an assignment operator?

As far as I can tell, this syntax triggers the Add method on MailAddressCollection, but I can't find the documentation that explains this magic for MailAddressCollection, or if it relates to either the Collection<T> type that it derives or the interfaces it inherits.

To show that the above syntax is being treated differently, the following approaches give compile time errors, complaining that the To property is readonly:

// Attempt 1

var mail = new MailMessage
{
    To = "hello@abc.com"
};

// Attempt 2

var mail = new MailMessage();
mail.To = { "hello@abc.com" }

// Attempt 3

var mail = new MailMessage
{
    To = new MailAddressCollection()
};

I'm sure there are other examples of this type of initialisation, but MailMessage is the first time I have come across it.

Ayb4btu
  • 3,208
  • 5
  • 30
  • 42

1 Answers1

4

Let's try to answer your questions one at a time

Q1. Why does the code below work?

var mail = new MailMessage
{
    To = { "hello@abc.com" }
};

A1. The To property is essentially a read-only property in which you can only assign a value during object construction. The "magic" is delivered by Collection Initializer which calls Add on types of IEnumerable with that syntax. MailAddressCollection is aCollection<MailAddress> which in turn implements IEnumerable.

As you have deduced, that code is practically equivalent to

var mail = new MailMessage();
mail.To.Add("hello@abc.com");

Documentation at https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers

Q2. Why doesn't the following codes work?

A2.

Attempt1 - you can't assign a string to a collection
Attempt2 - the property is read-only
Attempt3 - the property is read-only
Migg
  • 464
  • 5
  • 13
  • Ok, so it uses the collection initialiser syntax, what I'm not following is how it bypasses the `readonly` aspect of `To`. I thought readonly properties could only be set from the constructor, and object initialiser syntax occurs after the constructor call. Is there any documentation on the initialisation order of steps? – Ayb4btu Sep 30 '18 at 20:10
  • To is assigned inside the constructor. Take note you arent doing ‘To = new MailAddressCollection {“me@email.com”}’ so you arent violating the readonly modifier – Migg Oct 01 '18 at 15:22