Why do i receive error in the following declaration ?
List<int> intrs = new List<int>().AddRange(new int[]{1,2,3,45});
Error :Can not convert type void to List ?
Because AddRange function does not return a value. You might need to perform this in two steps:
List<int> intrs = new List<int>();
intrs.AddRange(new int[]{1,2,3,45});
You could also use a collection initializer (assuming C# 3.0+).
List<int> intrs = new List<int> { 1, 2, 3, 45 };
Edit by 280Z28: This works for anything with an Add method. The constructor parenthesis are optional - if you want to pass thing to a constructor such as the capacity, you can do so with List<int>(capacity) instead of just List<int> written above.
Here's an MSDN reference for details on the Object and Collection Initializers.
Dictionary<string, string> map = new Dictionary<string, string>()
{
{ "a", "first" },
{ "b", "second" }
};
Because AddRange modifies the specified list instead of returning a new list with the added items. To indicate this, it returns void.
Try this:
List<int> intrs = new List<int>();
intrs.AddRange(new int[]{1,2,3,45});
If you want to create a new list without modifying the original list, you can use LINQ:
List<int> intrs = new List<int>();
List<int> newIntrs = intrs.Union(new int[]{1,2,3,45}).ToList();
// intrs is unchanged
AddRange does not return the list it has added items to (unlike StringBuilder). You need to do something like this:
List<int> intrs = new List<int>();
intrs.AddRange(new int[]{1,2,3,45});
AddRange() is declared as:
public void AddRange(object[]);
It does not return the list.
By the way in C# 3.x (not sure about 2.0) you can do either of
List<int> intrs = new List<int>{1,2,3,45};
List<int> intrs = new []{1,2,3,45}.ToList(); // with Linq extensions
Besides other answers, you can add your own extension method that will add range and return list (not that it's a good practice).
BTW, if you had already declared intrs, you could have done it with parentheses:
(intrs = new List<int>()).AddRange(new int[] { 1, 2, 3, 45 });
However, I like the initialization syntax better.
Although others have already mentioned that AddRange does not return a value, based on the samples given for alternatives it should also be remembered that the constructor of List will take an IEnumerable of T as well in addition to the code previously mentioned that is .NET 3.5+
For example:
List<int> intrs = new List<int>(new int[]{2,3,5,7});
There is yet another way.
List<int> intrs = new List<int>
{
1,
2,
3,
45
};
Related
List implements IList so I expect IList will accept a List object
but why IList> doesn't accept List>?
static IList<int> List_1()
{
List<int> list = new List<int> { 1,2,3,3,4,5};
return list;
}
static IList<IList<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent; //compiler error CS0266
}
That's because of
List<T> implements IList<T> but
List<List<T>> does not implement IList<IList<int>>
That's why your first method works as intended and second not.
Just change your declaration of the list in the second method to
List<IList<int>> parent = new List<IList<int>>();
And this is the case of covariance and contravariance.
Generic type parameters support covariance and contravariance but you need to define in that way
By learn.microsoft.com
Covariance and contravariance are terms that refer to the ability to use a more derived type (more specific) or a less derived type (less specific) than originally specified. Generic type parameters support covariance and contravariance to provide greater flexibility in assigning and using generic types
Suppose this works. Your client code is:
var result = List_2();
Since the contract allows adding to the result anything that's IList<int>, you could possibly have
public class MyCustomIList : IList<int>
{
...
}
and then
var result = List_2();
result.Add( new MyCustomIList() );
But that's wrong!
Your result is a list of List<int>, you should not be allowed to add anything other than List<int> or its derivatives there. However, you were able to add MyCustomIList which is not related to the List<int>.
If you need a broad picture of the issue, read more on covariance and contravariance.
The fundamental issue in this particular example comes from the Add operation. If you don't need it, the IEnumerable will do
static IEnumerable<IEnumerable<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent; // no error, this works
}
This has been covered already.
Why then does List implement IList?
It is a bit odd, since List for any type other than object does not
fulfill the full contract of IList. It's probably to make it easier on
people who are updating old C# 1.0 code to use generics; those people
were probably already ensuring that only the right types got into
their lists. And most of the time when you're passing an IList around,
it is so the callee can get by-index access to the list, not so that
it can add new items of arbitrary type.
I would suggeste return IEnumerable instead of IList, will simplify your life, since List Fully implements it.
The problem is with your method return type. Modify your method signature to return to IList<List<int>> rather than returning IList<IList<int>>
static IList<List<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent; //no compiler error
}
Now it will work fine as your method now returns an IList of List<int>
I don't know why you want to return exactly IList<IList<int>>, but one way of doing that is to use Cast<T>() method:
static IList<IList<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent.Cast<IList<int>>().ToList();
}
Or ConvertAll() method:
return parent.ConvertAll(x => (IList<int>)x);
Both methods will run over all elemets, and cast/convert them to a given type, so I think it would be better to return IList<List<int>> instead (if that's possible).
This might not be a big deal but can someone please let me know what is the big difference of populating a list of int(s) on following code? for me the first way is using the constructor but not getting the point of new int[] there?! and totally confused on second way!
List<int> list1 = new List<int>(new int[]{ 1, 2, 3 });
List<int> list2 = new List<int>() { 1, 2, 3 };
List<int> list1 = new List<int>(new int[]{ 1, 2, 3 }); calls constructor with IEnumerable parameter.
List<int> list2 = new List<int>() { 1, 2, 3 };
Is equal to
list2.Add(1);
list2.Add(2);
list2.Add(3);
From documentation:
Collection initializers let you specify one or more element
initializers when you initialize a collection type that implements
IEnumerable and has Add with the appropriate signature as an instance
method or an 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.
I'm new in c#. I just want to ask if it is possible to insert a list object inside a c# list just like in python? C# addrange only insert multiple item at once but not a list object.
For example:
lst = [[1,2,3],[4,5,6],[7,8,9]]
Yes, but is much more verbose than python.
As some comments already answered, you can use a List of List to create something like your python example:
List<List<int>> listOfLists = new List<List<int>>() { new List<int>() {1,2,3}, new List<int>() {4,5,6}, new List<int>() {7,8,9}};
You can also make a list of different objects just declaring it a List of Objects:
List<object> listOfObjects = new List<object>();
listOfObjects.Add(new List<int>() { 1, 2, 3 }); // Adding list of int
listOfObjects.Add("text"); // Adding string
listOfObjects.Add(new float[] { 1.42f, 51.7f}); // Adding array of float
listOfObjects.AddRange(listOfObjects); // Duplicating all the elements of listOfObjects
listOfObjects.AddRange(listOfLists); // Adding all elments of the list listOfLists
List AddRange is just a way of adding many elements at once inside a list.
I'd like to use Remove() method on list of lists, but it's not working for me.
Simple example should say everything:
List<List<int>> list = new List<List<int>>();
list.Add(new List<int> { 0, 1, 2 });
list.Add(new List<int> { 1, 2 });
list.Add(new List<int> { 4 });
list.Add(new List<int> { 0, 1, });
list.Remove(new List<int> { 1, 2 });
If I use RemoveAt(1) it works fine but Remove() not.
It is obviously the same reason that this code returns false:
List<int> l1 = new List<int>();
List<int> l2 = new List<int>();
l1.Add(1);
l2.Add(1);
bool b1 = l1 == l2; // returns False
bool b2 = l1.Equals(l2); // returns False too
So it seems to me that I cannot simply compare two lists or even arrays. I can use loops instead of Remove(), but there must be easier way.
Thanks in advance.
The problem is that List<T> doesn't override Equals and GetHashCode, which is what List<T> will use when trying to find an item. (In fact, it will use the default equality comparer, which means it'll use the IEquatable<T> implementation if the object implements it, and fall back to object.Equals/GetHashCode if necessary). Equals will return false as you're trying to remove a different object, and the default implementation is to just compare references.
Basically you'd have write a method to compare two lists for equality, and use that to find the index of the entry you want to remove. Then you'd remove by index (using RemoveAt). EDIT: As noted, Enumerable.SequenceEqual can be used to compare lists. This isn't as efficient as it might be, due to not initially checking whether the counts are equal when they can be easily computed. Also, if you only need to compare List<int> values, you can avoid the virtual method call to an equality comparer.
Another alternative is to avoid using a List<List<int>> in the first place - use a List<SomeCustomType> where SomeCustomType includes a List<int>. You can then implement IEquatable<T> in that type. Note that this may well also allow you to encapsulate appropriate logic in the custom type too. I often find that by the type you've got "nested" collection types, a custom type encapsulates the meaning of the inner collection more effectively.
First approach:
List<int> listToRemove = new List<int> { 1, 2 };
list.RemoveAll(innerList => innerList.Except(listToRemove).Count() == 0);
This also removes the List { 2, 1 }
Second approach (preferred):
List<int> listToRemove = new List<int> { 1, 2 };
list.RemoveAll(innerList => innerList.SequenceEqual(listToRemove));
This removes all lists that contain the same sequence as the provided list.
List equality is reference equality. It won't remove the list unless it has the same reference as a list in the outer list. You could create a new type that implements equality as set equality rather than reference equality (or you do care about order as well?). Then you could make lists of this type instead.
This simply won't work because you're tying to remove a brand new list (the new keyword kind of dictates such), not one of the ones you just put in there. For example, the following code create two different lists, inasmuch as they are not the same list, however much they look the same:
var list0 = new List<int> { 1, 2 };
var list1 = new List<int> { 1, 2 };
However, the following creates one single list, but two references to the same list:
var list0 = new List<int> { 1, 2 };
var list1 = list0;
Therefore, you ought to keep a reference to the lists you put in there should you want to act upon them with Remove in the future, such that:
var list0 = new List<int> { 1, 2 };
listOfLists.Remove(list0);
They are different objects. Try this:
List<int> MyList = new List<int> { 1, 2 };
List<List<int>> list = new List<List<int>>();
list.Add(new List<int> { 0, 1, 2 });
list.Add(MyList);
list.Add(new List<int> { 4 });
list.Add(new List<int> { 0, 1, });
list.Remove(MyList);
You need to specify the reference to the list you want to remove:
list.Remove(list[1]);
which, really, is the same as
list.RemoveAt(1);
How do I convert an Array to a List<object> in C#?
List<object> list = myArray.Cast<Object>().ToList();
If the type of the array elements is a reference type, you can leave out the .Cast<object>() since C#4 added interface co-variance i.e. an IEnumerable<SomeClass> can be treated as an IEnumerable<object>.
List<object> list = myArray.ToList<object>();
Use the constructor: new List<object>(myArray)
List<object>.AddRange(object[]) should do the trick. It will avoid all sorts of useless memory allocation.
You could also use Linq, somewhat like this: object[].Cast<object>().ToList()
The List<> constructor can accept anything which implements IEnumerable, therefore...
object[] testArray = new object[] { "blah", "blah2" };
List<object> testList = new List<object>(testArray);
private List<object> ConvertArrayToList(object[] array)
{
List<object> list = new List<object>();
foreach(object obj in array)
list.add(obj);
return list;
}
If array item and list item are same
List<object> list=myArray.ToList();
Everything everyone is saying is correct so,
int[] aArray = {1,2,3};
List<int> list = aArray.OfType<int> ().ToList();
would turn aArray into a list, list. However the biggest thing that is missing from a lot of comments is that you need to have these 2 using statements at the top of your class
using System.Collections.Generic;
using System.Linq;
I hope this helps!
You can also initialize the list with an array directly:
List<int> mylist= new List<int>(new int[]{6, 1, -5, 4, -2, -3, 9});
You can try this,
using System.Linq;
string[] arrString = { "A", "B", "C"};
List<string> listofString = arrString.OfType<string>().ToList();
Hope, this code helps you.
another way
List<YourClass> list = (arrayList.ToArray() as YourClass[]).ToList();
Here is my version:
List<object> list = new List<object>(new object[]{ "test", 0, "hello", 1, "world" });
foreach(var x in list)
{
Console.WriteLine("x: {0}", x);
}
This allow you to send an object:
private List<object> ConvertArrayToList(dynamic array)