Why is the Add method necessary for {} initialization?

Use initialization syntax as follows:

var contacts = new ContactList { { "Dan", " dan.tao@email.com " }, { "Eric", " ceo@google.com " } }; 

... I understand that my ContactList type must define an Add method that takes two string parameters

 public void Add(string name, string email); 

What confuses me a bit is that the initializer { } syntax seems most useful when creating read-only or fixed-size collections . After all, it is intended to mimic the initialization syntax for an array, right? (OK, so arrays are not read-only, but they are a fixed size.) And, of course, it can only be used when the contents of the collection are known (at least the number of elements) at compile time.

Thus, it would seem that the basic requirement for using the initializer syntax of this collection (having the Add method and, therefore, a mutable collection) does not correspond to the typical case in which it would be very useful.

I am sure that I did not think about this issue as a C # development team; it just seems that there may be different rules for this syntax that would better match its typical usage scenarios.

Am I really here? Is it advisable to use the { } syntax to initialize fixed-size collections not as often as I think? What other factors could affect the wording of the requirements for this syntax, which I simply don’t think about?

+4
source share
9 answers

The reason for this is that it has been modernized. I agree with you that using a constructor that takes a collection will make much more sense, but not all existing collection classes have implemented this, and the change should (1) work with all existing collections, (2) not modify existing classes in any way.

His compromise.

+2
source

I am sure that I did not think about this issue as a C # development team; it just seems that there may be different rules for this syntax that would better match its typical usage scenarios.

Your analysis is very good; The key problem is the last three words in the above statement. What are the actual typical use cases?

The goal, based on typical usage scenarios for collection initializers, was to make it possible to initialize existing collection types in expression syntax so that collection initializers can be embedded in query understanding or converted into expression trees.

Each other scenario was a lower priority; A function exists in general because it helps LINQ to work.

The C # 3 compiler command was the "long pole" for this version of Visual Studio / .NET. We had most days of work on the schedule of any team, which meant that every day we delayed, the product would be delayed. We wanted to send a quality product on time to all of you guys, and the perfect is the enemy of the good. Yes, this function is a bit clumsy and does not do absolutely everything that you may need, but it was more important to get it robust and tested for LINQ than to make it work on a bunch of immutable collection types that to a large extent do not even exist.

If this feature was developed in the language from day one, while the types of frameworks were still evolving, I’m sure everything would have gone differently. As we discussed elsewhere on this site, I would very much like to have an array of values ​​of a fixed size with a record at a time. It would be nice to define a common template for creating a state heap to initialize an arbitrary immutable collection. You are right that the collection initializer syntax is perfect for such a thing.

Features like these are listed on the list of possible future versions of hypothetical languages, but not too high on the list. In other words, let me get async / await first, before we think too much about syntactic sugars to initialize an immutable collection.

+10
source

This is because the initialization instruction is short for CLR. When it compiles to bytecode, it is called by the Add method that you defined.

So, you can make this initialization operator not be a "first class" function, because it does not have an analogue in IL. But this is the case for quite a lot of what we use, for example, the expression "using".

+3
source

The main reason is syntactic sugar .

Initializer syntax simplifies C # write programming. This does not actually add any expressive language features.

If the initializer does not need the Add() method, then it will be a completely different function than now. Basically, this is just not how C # works. There is no literal to create shared collections.

+2
source

Not an answer, strictly speaking, but if you want to know what things influenced the design of the initializers of the collection, then you will probably find this interesting:

+2
source

What should initialization syntax use if not the Add method? The initialization syntax is "started" after the collection constructor is started, and the collection is completely created. There must be some way to add items to the collection after it's created.

If you want to initialize a read-only collection, do it in the constructor (taking the argument T[] items or similar)

+1
source

As far as I understand, the syntax of the collection initializer is syntactic sugar without any special tricks. It was developed in part to support initialization of collections within Linq queries:

 from a in somewhere select new { Something = a.Something Collection = new List<object>() { a.Item1, a.Item2, ... } } 

There used to be no way to do this inline, and you would have to do it after an event that was unpleasant.

+1
source

I would like to have initializer syntax for immutable types (both for collections and for regular types). I think this can be implemented using a special constructor overload using syntax similar to params .

For example, something like this:

 MyClass(initializer KeyValuePair<K,V>[] initialValues) 

But, unfortunately, the C # team has not yet implemented such a thing :(

So we need to use a workaround like

 MyClass(new KeyValuePair<K,V>[]{...}) 

until

+1
source

Expression collection initializers, so you can use them where only an expression is valid, such as a field initializer or LINQ query. This makes their existence very useful.

I also find that the initialization type { } in braces looks like a fixed-size collection, but it's just a syntax choice.

+1
source

Source: https://habr.com/ru/post/1238896/


All Articles