Is is possible to combine a List initializer and object initializer at the same time?
Given the following class definition:
class MyList : List<int>
{
public string Text { get; set; }
}
// we can do this
var obj1 = new MyList() { Text="Hello" };
// we can also do that
var obj2 = new MyList() { 1, 2, 3 };
// but this one doesn't compile
//var obj3 = new MyList() { Text="Hello", 1, 2, 3 };
Is this by design or is it just a bug or missing feature of the c# compiler?
No, looking at the definitions from section 7.6.10 of the C# spec, an object-or-collection-initializer expression is either an object-initializer or a collection-initializer.
An object-initializer is composed of multiple member-initializers, each of which is of the form initializer = initializer-value whereas a collection-initializer is composed of multiple element-initializers, each of which is a non-assigment-expression.
So it looks like it's by design - possibly for the sake of simplicity. I can't say I've ever wanted to do this, to be honest. (I usually wouldn't derive from List<int> to start with - I'd compose it instead.) I would really hate to see:
var obj3 = new MyList { 1, 2, Text = "Hello", 3, 4 };
EDIT: If you really, really want to enable this, you could put this in the class:
class MyList : List<int>
{
public string Text { get; set; }
public MyList Values { get { return this; } }
}
at which point you could write:
var obj3 = new MyList { Text = "Hello", Values = { 1, 2, 3, 4 } };
No, it's a not a bug. It is by design of the language.
When you write
var obj1 = new MyList() { Text="Hello" };
this is effectively translated by the compiler to
MyList temp = new MyList();
temp.Text = "Hello";
MyList obj = temp;
When you write
var obj2 = new MyList() { 1, 2, 3 };
this is effectively translated by the compiler to
MyList temp = new MyList();
temp.Add(1);
temp.Add(2);
temp.Add(3);
MyList obj2 = temp;
Note that in the first case you are using an object initializer, but in the second case you are using a collection initializer. There is no such thing as an object-and-collection intializer. You are either initializing the properties of your object, or you are initializing the collection. You can not do both, this is by design.
Also, you shouldn't derive from List<T>. See: Inheriting List<T> to implement collections a bad idea?
If you want to get something like this functionality, consider making a constructor argument:
var x = new CustomList("Hello World") { 1, 2, 3 }
I've just read this question.
If we have property of dictionary type:
public class Test
{
public Dictionary<string, string> Dictionary { get; set; } = new Dictionary<string, string>
{
{"1", "1" },
{"2", "2" },
};
}
Then we can construct object and add value to it
var test = new Test { Dictionary = { { "3", "3" } } };
Console.WriteLine(test.Dictionary.Count); // 3
And I don't understand the point why such a confusing syntax to add items exists? When looking at someone else code it's very easy to confuse it with very similarly looking
var test = new Test { Dictionary = new Dictionary<string, string> { { "3", "3" } } };
Console.WriteLine(test.Dictionary.Count); // 1
I'd be more OK with it if following would be possible (but it's not):
var dictionary = new Dictionary<string, string> { { "1", "1" } };
...
// adding a new value
dictionary = { { "2" , "2"} }; // invalid expression term '{'
So why this form of adding was needed and exists? For interviews?
The collection initializer syntax is simply a convenient way of initializing collections (including dictionaries) as part of a complex object model using an object initializer. For example:
var model = new SomeModel {
Name = "abc",
Id = 42,
SpecialMaps = {
{ "foo", "bar" },
{ "magic", "science" },
}
};
If you don't like it: just don't use it; but the equivalent with manual .Add is IMO much less elegant - a lot of things are taken care of automatically, such as only reading the property once. The longer version that actually creates the collection at the same time works very similarly.
Note that there is also an indexer variant now:
var model = new SomeModel {
Name = "abc",
Id = 42,
SpecialMaps = {
["foo"] = "bar",
["magic"] ="science",
}
};
This is very similar, but instead of using collection.Add(args); it uses collection[key] = value;. Again, if it confuses you or offends you: don't use it.
Take this example where the constructor of Thing creates a Stuff and the constructor of Stuff creates the Foo list
var thing = new Thing();
thing.Stuff.Foo.Add(1);
thing.Stuff.Foo.Add(2);
thing.Stuff.Foo.Add(3);
And now you can simplify it to the following with initializers.
var thing = new Thing
{
Stuff.Foo = { 1, 2, 3 }
};
You can only use this type of initialization for a collection without first newing up the collection when nested because the collection can exist in this case, but cannot when assigning directly to a variable.
Ultimately this type of syntactic sugar is likely added by the language designers when they see code patterns that they think can be simplified.
I want to create a list of array type.
I want to create array containing values :
array = [a,b];
Then i want to put this array in list :
List<Array> list = new List<Array>( );
I am able to do this with list of string type but no luck with array type :
List<String> list = new List<String>( );
I am from javascript background, not much familiar with concept of collections in c#.
Also how can i create array in c# like we do in javascript :
var arrTemp = ["a", "b"];
Well, since your array is string[]:
var arrTemp = ["a", "b"];
you have to declare the required list as List<string[]>:
// list of string arrays
List<string[]> list = new List<string[]>() {
new string[] {"a", "b"}
};
In case you want to be able to put any array into the list declare it as loose as possible (List<object[]>):
// list of abitrary arrays
List<object[]> list = new List<object[]>() {
new string[] {"a", "b"},
new double[] {123.45, 789.12, 333.55},
new object[] {'a', "bcd", 1, 244.95, true},
};
Hope this can help you
var test = new List<int[]>();
You can actually create a list of arrays:
var listOfArrays = new List<Array>();
The problem with this is that it's difficult to use the arrays themselves, as the Array type doesn't support array syntax. (e.g. You can't do listOfArrays[0][0]) Instead, you have to use the GetValue method to do your retrieval:
var obj = listOfArrays[0].GetValue(0);
But this has another problem. The GetValue method returns object, so while you could always cast it to the desired type, you lose your type safety in choosing this approach.
Alternatively, you could just store object[] arrays:
var listOfArrays = new List<object[]>();
var obj = listOfArrays[0][0];
But while this solves the issue of the array notation, you still lose the type safety.
Instead, if at all possible, I would recommend finding a particular type, then just have arrays of that type:
var listOfArrays = new List<string[]>();
string s = listOfArrays[0][0];
for example, an array of strings would be
var arrayOfString = new string[]{"a","b"};
// or shorter form: string[] arrayOfString = {"a","b"};
// also: var arrayOfString = new[] { "a", "b" }
And then creating a list-of-arrayOfString would be
var listOfArrayOfString = new List<string[]>();
This works with any type, for example if you had a class MyClass
var arrayOfMyClass = new MyClass[]{ ... }; // ... is you creating instances of MyClass
var list = new List<MyClass[]>();
List<string> icons = new List<string>[]
{
"!","!","N","N",",",",","k","k",
"b","b","v","v","w","w","z","z"
}
If i try to use code from above, compiler throws a message Error "; expected",
also if i add ";" at the end of the braces everything looks fine until i try to compile the program, then i get Error for each character in the list:
"Cannot implicitly convert type 'string' to 'System.Collections.Generic.List'"
And also another error that looks like this:
"Error 17 Cannot implicitly convert type 'System.Collections.Generic.List[]' to 'System.Collections.Generic.List'"
I need to mention that i use visual studio 2005, and I'm thinking perhaps this could be a reason why list doesn't works, since it worked for me in the newer version of visual studio 2015.
I am aware that List should look something like one from below, but if i try to use this syntax i get even more errors, and it looks like whole code is getting messed up.
List<string> icons = new List<string>()
{
"!","!","N","N",",",",","k","k",
"b","b","v","v","w","w","z","z"
}
Your second syntax is correct for C# 3.0 and later (though missing the final ;). See this fiddle for a demo.
List<string> icons = new List<string>()
{
"!","!","N","N",",",",","k","k",
"b","b","v","v","w","w","z","z"
};
Note that the () when using a collection initialiser { ... } is optional, so this could be written as:
List<string> icons = new List<string>
{
"!","!","N","N",",",",","k","k",
"b","b","v","v","w","w","z","z"
};
Your first attempt uses [], which attempts to initialise an array of List<string>. Each item in the initialiser (e.g. "!") would then be expected to be a List<string>. This isn't what you intended.
However, you state you are using Visual Studio 2005, which shipped with the C# 2.0 compiler. As this syntax was introduced in C# 3.0, so you won't be able to use it. You should ideally upgrade to a later version. The C# 2.0 equivalent syntax would be:
List<string> icons = new List<string>();
icons.Add("!");
icons.Add("!");
icons.Add("N");
// ...
The correct way is:
List<string> icons = new List<string>()
{
"!","!","N","N",",",",","k","k",
"b","b","v","v","w","w","z","z"
};
var icons = new List<string>()
{
"!","!","N","N",",",",","k","k",
"b","b","v","v","w","w","z","z"
};
You have to complete the statement with the semicolon (;) at the end
List<string> icons = new List<string>()
{
"!","!","N","N",",",",","k","k",
"b","b","v","v","w","w","z","z"
};
You're missing a ;. You should not put ; at the end of new List<string>() in case you want to use the intializer list syntax:
List<string> icons = new List<string>()
{
"!","!","N","N",",",",","k","k",
"b","b","v","v","w","w","z","z"
};
A statement can consist of a single line of code that ends in a
semicolon, or a series of single-line statements in a block. A
statement block is enclosed in {} brackets and can contain nested
blocks
Collection initializers
Collection initializers let you specify one or more element
initializers when you initialize a collection class that implements
IEnumerable or a class with an Add 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 to the Add method of the class in your source
code; the compiler adds the calls.
The following examples shows two simple collection initializers:
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
For C# 2.0 use this:
List<string> strings = new List<string>(new string[] { "1", "2", "3" });
You need a ; after closing }
List<string> icons = new List<string>()
{
"!","!","N","N",",",",","k","k",
"b","b","v","v","w","w","z","z"
};
and make sure you using
using System.Collections.Generic;
I'm quite new to using predicates for finding something specific within a collection.
Here's my example:
static void FindPersons(string firstLetter)
{
List<string> names = new List<string>()
{"Marcus", "John", "Jesse", "Lance", "Aaron", "Archibald", "Victor"
};
List<string> names2 = names.FindAll(a => a.StartsWith(firstLetter));
foreach (var name in names2)
{
Console.WriteLine(name);
}
}
I'd call the method within Main:
FindPersons("a");
I had to use string for the first letter because StartsWith takes string as a parameter (or I could use char and ToString().
How can I do this using this shorter syntax?
One more question - Generally, how often during your work you use predicates to find specific objects within a collection?
Thanks.
Just use Console.WriteLine(string.Join<string>("\n", result)); as following method to do that.
static void FindPersons(string firstLetter)
{
List<string> names = new List<string>()
{"Marcus", "John", "Jesse", "Lance", "Aaron", "Archibald", "Victor"
};
List<string> result = names.Where(a => a.StartsWith(firstLetter, StringComparison.InvariantCultureIgnoreCase)).ToList();
Console.WriteLine(string.Join<string>("\n", result));
}