Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default Type for Collection and Object Initializers (List and Dictionary) #5865

Closed
alrz opened this issue Oct 11, 2015 · 8 comments
Closed

Comments

@alrz
Copy link
Contributor

alrz commented Oct 11, 2015

Since most common types that are used with collection initializers, are lists and dictionaries. It would be nice to provide a concise syntax for creating them by making List<> and Dictionary<> default for collection initializers and object initializers respectively.

Currently following statements are legal.

int[] array = { 1, 2, 3 };
var array = new[] { 1, 2, 3 };
var list = new List<int> { 1, 2, 3 };
var dict = new Dictionary<int,int> { ["key"] = "value" };

With syntax proposed in this topic you'd be able to write:

var list = { 1, 2, 3 };           // List<int>
var dict = { ["key"] = "value" }; // Dictionary<string,string>

It should be able to infer the default type by usage:

Collection<int> collection = { 1, 2, 3 };
  • For backward compatibility, using shortened syntax in object initializers mustn't create a new list/dictionary e.g. new Foo { List = { 1, 2, 3 } } initializes the existing list (if not null) with listed elements. However, as long as it's not ambiguous with anonymous types, we can use a new keyword to explicitly create a new list: new Foo { List = new { 1, 2, 3 } }.
  • To avoid additional casts, list elements and dictionary keys and values should infer the most common type, e.g. { [1] = 1, [2] = "" } returns a Dictionary<int, object>.
  • This is also consistent with list and indexer patterns proposed in Proposal: List, Indexer (Dictionary) and String Patterns #5811.
@alrz
Copy link
Contributor Author

alrz commented Oct 11, 2015

In expression-bodied methods this wouldn't be ambiguous since currently F() => { ... } is not allowed, but in expression-bodied lambda expressions this would be problematic: () => { 1 }? Would C# introduce [ ] syntax for lists?

@aluanhaddad
Copy link

Why propose a dictionary initializer that deviates from existing syntax?
I think you should change

// dictionary
var dict = { 
    "key1": "value1", 
    "key2": { 1: "value", 2: "string" }
};

to

// dictionary
var dict = { 
    ["key1"] = "value1", 
    ["key2"] = { [1] = "value", [2] = "string" }
};

@alrz
Copy link
Contributor Author

alrz commented Oct 11, 2015

@aluanhaddad the purpose is to provide a lightweight syntax for dictionaries, your example is not much different to what is possible right now with indexer initializers.

Indexer initializers as a generalized feature make sense because they can be used on all types with an indexer, not just dictionaries, on the other hand, since dictionary expression defaults to Dictionary<,> so why bother with the indexer syntax.

@aluanhaddad
Copy link

@alrz Because I do not think a third dictionary initializer syntax is a good idea. We already have

{
   { key1, value1 },
   { key2, value2 }
}

and

{
    [key1] = value1,
    [key2] = value2
}

both are already understood, and the latter is already lightweight and consistent with object initializer syntax. Additionally, what makes your proposed syntax lightweight is the constructor type inference, not the omission of 2 characters per dictionary entry.

Furthermore the comment in your first example

// list expression defaults to List<T>
var list = { 1, 2, 3 };
List<int> list = { 1, 2, 3 };

implies that the types targeted by the new syntax can be overridden. Is this correct? If not then this proposal is of extremely limited value. For example, If I can't initialize a readonly collection with the new syntax, I'm not interested.

@alrz
Copy link
Contributor Author

alrz commented Oct 11, 2015

@aluanhaddad The former is not an indexer initializer, it calls the Add method overloads based on expression-list you have provided in between of { } which basically provides a syntax for initializing dictionaries. The whole block is just a collection initializer. And the latter is an object initializer with an indexer being initialized.

Dictionary expressions are not intended to be used for initialization they are standalone expressions which return a dictionary.

the types targeted by the new syntax can be overridden. Is this correct?

No, I just wanted to show that the list expression returns a List<> and the second line which currently is a compiler-error becomes legal. Although, this is definitely a good idea to override the default type by the target type like

 // currently possible
int[] array = { 1, 2, 3 };
// list expression
var list = { 1, 2, 3 };
// your case
Collection<int> collection = { 1, 2, 3 };

basically, extended array-initializer syntax to support other collections.

If I can't initialize a readonly collection with the new syntax, I'm not interested.

This one actually depends on collection initializer specification, since currently it simply calls the void-returning Add method, it should extend to reuse the object returned by the Add method in ImmutableList<> for example.

@aluanhaddad
Copy link

The former is not an indexer initializer, it calls the Add method overloads based on expression-list you have provided in between of { } which basically provides a syntax for initializing dictionaries.

I totally forgot this because they were so often used with indexable collections, I stand corrected.

Dictionary expressions are not intended to be used for initialization they are standalone expressions which return a dictionary.

I suggest creating a separate proposal for this feature. Note that the title of this proposal is "Syntax for List and Dictionary (Extended Collection/Array Initializer)" which is why I thought you meant initializers. What you are proposing is a literal syntax for creating System.Collections.Generic.Dictionary<TKey, TValue> instances.

@alrz
Copy link
Contributor Author

alrz commented Oct 11, 2015

@aluanhaddad I've been thinking about this and your arguments, I come up with two ideas: I admitted that I'm not a fan of ranges, I just mentioned them here for the sake of completeness. so I'm thinking about narrowing this proposal to "default type for collection and object initializers" as you thought it was. and propose a new syntax (surprise) JSON literals.

@aluanhaddad
Copy link

@alrz Right on. You may want to look over #1746, #3910, and #3912 before formulating your proposal for JSON literals.

@alrz alrz changed the title Syntax for List and Dictionary (Extended Collection/Array Initializer) Default Type for Collection and Object Initializers (List and Dictionary) Oct 12, 2015
@alrz alrz closed this as completed Oct 14, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants