Concise way to initialise a collection - c#

I can initialise a class in a concise manner using something like:
public static readonly type TYPE_NAME = new type()
{
ClientIp = "ClientIp",
LanguageCode = "LanguageCode",
SessionToken = "SessionToken",
SystemKey = "SystemKey"
};
However is it possible to initialise a collection in a similar way (inherited from List<>)?

List<string> strList = new List<string>{ "foo", "bar" };
List<Person> people = new List<Person>{
new Person { Name = "Pete", Age = 12},
new Person { Name = "Jim", Age = 15}
};

Use a collection initializer
http://msdn.microsoft.com/en-us/library/bb384062.aspx
List<int> list = new List<int> { 1, 2, 3 };

Yes:
var l = new List<int>() { 1, 1, 2, 3, 5 };

You can surely use collection initializer.
To use this,
List<int> collection= List<int>{1,2,3,...};
To use collection initializer it need not to be exactly of List type.
Collection initializer can be used on those types that implements IEnumerable and has one public Add method.
You use Collection initializer feature even in the following type.
public class SomeUnUsefulClass:IEnumerable
{
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
public void Add(int i)
{
//It does not do anything.
}
}
Like,
SomeUnUsefulClass cls=new SomeUnUsefulClass(){1,2,3,4,5};
which is perfectly valid.

Related

How to initialize List inherits from List C#?

I am new to inherit from list concept and I have a little confusion of initializing that.
Here is a simple example of my real code, here is my class that inherits from list:
public class List_Of_Int : List<int>
{
public string key{get; set;}
public List_Of_Int(string key)
{
this.key = key;
}
}
and here is where I need to initialize my variable:
List<int> list_of_int = new List<int>() { 1, 2, 3 };
List_Of_Int list_of_list = new List_Of_Int("some_key") **Some Code**
I want to assign list_of_int to my list_of_list, I believe there's a code replace some code that will do that, Is it true?
I know I can add by using AddRange(list_of_int ) later but I'm just wondering if I can do it while declaration?
Just wondering what you are asking actually but I guess this is what probably you are looking at
public class List_Of_Int
{
public List<int> key {get; set;}
public List_Of_Int(List<int> key)
{
this.key = key;
}
}
You can now initialize like
List<int> list_of_int = new List<int>() { 1, 2, 3 };
List_Of_Int list_of_list = new List_Of_Int(list_of_int)

Understanding LINQ subquery

I used a normal query inside a foreach to reach my goal, but I think there is a better way.
int max = 0;
foreach(Area area in myZoo.AreaList)
{
max = (from a in area.AnimalList
select a.ID).Max();
}
return max;
How can I use a pure LINQ to get the max of all sublists? (Animal is a List of the class Animal inside the AreaList and contains an Int32 called ID) Erm, and Lambda is welcome, so don't hastitate to answer only because you only know the lambda answer ;)
public class Zoo
{
public List<Area> AreaList {get; set;}
}
public class Area
{
public List<Animal> AnimalList {get; set;}
}
public class Animal
{
public List<int> Id {get; set;}
}
Only the short form so no one gets confused ;)
Although SelectMany works, I feel query is more readable in such case.
var max = (from area in myZoo.AreaList
from animal in area.AnimalList
from id in animal.Id
select id).Max();
You are looking for a nested SelectMany.
SelectMany will return a single IEnumerable<T> from the many "inner" Ienumerable<T> - so Zoo.SelectMany(a => a.AreaList) will return a single IEnumerable<Area> containing all the IEnumerable<Area> from the Area property - then you do it one more time for the List<Animal> in the Area class:
Sample data:
var zoo = new Zoo() {
AreaList = new List<Area>()
{
new Area()
{
AnimalList = new List<Animal>()
{
new Animal() {Id = new List<int>() {1, 2, 3}},
new Animal() {Id = new List<int>() {4, 5, 6}}
}
},
new Area()
{
AnimalList = new List<Animal>()
{
new Animal() {Id = new List<int>() {7, 8, 9}},
new Animal() {Id = new List<int>() {10, 11}}
}
},
}
};
Linq query:
var max = zoo.AreaList.SelectMany(a => a.AnimalList).SelectMany(a => a.Id).Max();
Console.WriteLine(max);
Result: 11
In query syntax you can do SelectMany by chaining from clauses, as shown in gxp's answer. (Personally, I prefer the method chaining syntax, so it took me some time to figure that one out...)
var max = zoo.AreaList.Max(arl => arl.AnimalList.Max(anl => anl.Id)).Max();
The maximum value of all maximum values of all AnimalLists, and the Max of them.
That's effectievly the same as ZoharPeled's SelectMany, except he flattens the list and takes the max of all items where I take the max of each list again and again.

Error in return type-Class

I am new to C# and am testing on return types using array and a class. But Somehow I am stuck while trying to return a class' object. In class notWhole, I tried to pass an array as an argument to the constructor but somehow compiler throws an error saying "field initializer can't initialize non static field member".
class Whole
{
int[] Arr = new int[3];
public Whole()
{
}
public Whole(int[] arr)
{
Arr = arr;
}
public int[] Spit()
{
return Arr;
}
}
class notWhole
{
int[] arr = new int[] { 1, 2, 3 };
Whole w1 = new Whole(arr); //ERROR: can't pass an array(arr) as an argument
public Whole wow()
{
return w1;
}
}
I think that error message is enough to identify the reason, ie.,
A field initializer cannot reference the non-static field, method, or
property
So you can try like this:
Whole w1 = new Whole(new int[] { 1, 2, 3 });
or like this :
static int[] arr = new int[] { 1, 2, 3 };
Whole w1 = new Whole(arr);
C# does not allow you to access in initializers section other fields or methods
You could use a constructor for your purposes.
Also, if you use a static then you could create some side effects since all of your Whole instances will have a reference to same static array and a change in one of you Whole instance will be "available" in all others.
class notWhole
{
Whole w1;
public notWhole()
{
int[] arr = new int[] { 1, 2, 3 };
w1 = new Whole(arr);
}
public Whole wow()
{
return w1;
}
}

Create default item in a list and return new item

I would like to add a new item at the back of a list, and get the newly created item.
Let's assume that we could do something like this for one moment:
class Temp
{
public string First { get;set;}
public string Second { get;set;}
}
List<string> list = new List<string>();
var newItem = list.Push();
newItem.First="asd";
newItem.Second = "qwe;
this would be easier than
var newItem = new Temp();
newItem.First="asd";
newItem.Second = "qwe;
list.Add(newItem);
especially when I can't use auto-properties.
Is this possible?
Unless you implement your own List type and add the Push method, the only way you can do that is if the T in List can be constructed using a parameterless constructor.
Here's an extension method for that.
This is not recommended, but is an answer to your question.
Something along the lines of this - I did not compile or run this code
public static class ListEx {
public static T Push<T>(this List<T> list) where T: new() {
// Create an instance of T.
var instance = new T();
// Add it to the list.
list.Add(instance);
// Return the new instance.
return instance;
}
}
You can use object initializers:
var list = new List<Temp>();
list.Add(new Temp{ First = "abc", Second = "def" });
Or together with a collection initializer:
var list = new List<Temp> { new Temp{ First = "abc", Second = "def" } };
This turns your four liner into a one liner.
Or with more than one entry:
var list = new List<Temp> {
new Temp{ First = "abc", Second = "def" },
new Temp{ First = "ghi", Second = "jkl" },
new Temp{ First = "mno", Second = "pqr" }
};
And it should of course be a list of Temp instead of a list of string.

Is Inferred List Initializes possible?

I know that i can initialize a collection as follows
var array = []{"1", "2", "3"};
which will automatically infer that i want to create an Array of type String, But this will restrict me from Adding or removing indexes from the array since an Array has a fixed size.
Is there anyway to do the same with the Generic List type and the the compiler should infer which type "T" is based on the items in the initializer?
Maybe something like new List(){...}
No, this is not supported - you have to specify the type parameter but can still use collection initializers.
var list = new List<String> { "1", "2", "3" };
You could however create a helper method
public static class ListUtilities
{
public static List<T> New<T>(params T[] items)
{
return new List<T>(items);
}
}
and use it like this.
var list = ListUtilities.New("1", "2", "3");
But this is probably not worth it, you don't gain much if anything at all. And this will create an array first and use it to populate a list. So this is not that different from Keith Nicholas' var list = new[] { "1", "2", "3" }.ToList();.
Here's a pretty nifty example:
static void Main(string[] args)
{
var Customer = new { FirstName = "John", LastName = "Doe" };
var customerList = MakeList(Customer);
customerList.Add(new { FirstName = "Bill", LastName = "Smith" });
}
public static List<T> MakeList<T>(T itemOftype)
{
List<T> newList = new List<T>();
return newList;
}
http://kirillosenkov.blogspot.com/2008/01/how-to-create-generic-list-of-anonymous.html
var list = new[] {"1", "2", "3"}.ToList();
Yes. But no inference .
var li = new List<int> {1,2,3,4,5,6};
Closest you will get is
var li = new List<dynamic> {1,2,3,4,5}

Categories

Resources