How to convert unioned generic list to generic list? - c#

I have two generic list that have been unioned. Say listA and listB, both of type List<SomeType>.
listA.Union(listB);
The unioned set is of type System.Linq.Enumerable.UnionIterator<string>, which isn't the same as List<SomeType>.
I have tried casting:
listA.Union(listB).ToList<SomeType>();
and
(List<SomeType>)listA.Union(listB);
Both fail. I tried to access ForEach(), thinking I could add the result to a new list. .Foreach() isn't available.
I could use a traditional foreach and add each item to a List<SomeType> variable. However, is there a lambda statement that can do the conversion in one line, assigning to a variable of type List<SomeType>?

You don't have to explicitly cast the List in ToList method. If both the list are of same type, you can simply do ToList in the end to get a List of the same type.
List<MyClass> listA = new List<MyClass>();
List<MyClass> listB = new List<MyClass>();
List<MyClass> temp = listA.Union(listB).ToList(); //Just do ToList at the end.
Explicitly specifying the type in ToList method should work as well. I am not sure why its not working.

Union is an extension method on IEnumerable<T> interface, not on List<T>, so it doesn't know or care that you are trying to connect lists and thus does not create one as a result unless you call ToList explicitly.
If you want to 'attach' one list to another, you might want to use AddRange method instead.

Related

difference between IEnumerable<T>.Reverse & List<T>.Reverse [duplicate]

This question already has answers here:
Why there is two completely different version of Reverse for List and IEnumerable?
(3 answers)
Closed 7 years ago.
Why IEnumerable<T>.Reverse() returns the reversed collection with the original collection and List<T> reverses the original collection itself? This is somewhat confusing to me since List<T> inherits from IEnumerable<T>.
Because they're two different methods.
List<T>.Reverse is an instance method on List<T>. This modifies the List in place.
Enumerable.Reverse<T> is an extension method on IEnumerable<T>. This creates a new sequence that enumerates the source sequence in reverse order.
You can use the latter on a List<T> by calling as a static method:
var list = new List<string>{"1","2"};
var reversed = Enumerable.Reverse(list)
Or by casting to IEnumerable<T>:
IEnumerable<string> list = new List<string>{"1","2"};
var reversed = list.Reverse();
In both these cases, list remains unchanged and reversed when enumerated returns {"2","1"}.
Conceptually, this may be because IEnumerable is used when you want to represent an immutable collection of items. That is, you only want to read the items in the list, but not add/insert/delete or otherwise change the collection. In this view of the data, returning a new IEnumerable in a different order is the expected result. When you use a List, you expected to be able to add/insert/delete or otherwise mutate the collection, so a Reverse method that changes the order of the original list would be expected in that context.
As others have noted IEnumerable is an interface and List is a class. List implements IEnumerable.
So,
IEnumerable<String> names = new List<String>();
var reversedNames = names.Reverse();
gets you a second list, reversed.
Whereas,
List<String> names = new List<String>();
names.Reverse();
Reverses your original list. I hope this makes sense.
Reverse on IEnumerable<T> is part of Linq and is added as extension method (Enumerable.Reverse<T>). It was added after Reverse was implemented for List<T>.
IEnumerable<T> isn't a collection of objects either. It just tells the consumer how to get at those items.
These are different methods, remember. Essentially different, with nothing common but a name.
void List.Reverse is a method of List instance only, and it does in place reversal of list or part of it.
IEnumerable Enumerable.Reverse is an extension method (btw IList also has it!) creates a new enumerable with order reversed.
There is no such thing as IEnumerable<T>.Reverse() It's Enumerable.Reverse<T>(this IEnumerable<T>) and it's extension method from Linq applied to all IEnumerable<>.
Now that we've established when they come from, it's easy to understand why they are so different. Linq adds methods for creating "processing streams", and it's achieved by creating new instance every time.
List<T>.Reverse() is a method of List and like all it's methods (eg Add) directly modifies the instance.
IEnumerable<T> has an underlying implementation, which could be List<T>, Hashtable<T> or something else that implements IEnumerable.
List<T> itself is the implementation, so you can directly modify that instance.
And as everyone else has mentioned, one is an extension method and part of Linq, and one is implemented directly on the type.

How to cast List<object> to List<SomethingElse>

How can i cast a List<object> to List<SomethingElse>?
(where SomethingElse is known to descend from object)
Bonus Chatter
Casting the list:
List<Object> first = ...;
List<SomethingElse> second = (List<SomethingElse>)first;
doesn't work:
Cannot convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
Casting the list:
List<SomethingElse> second = first.Cast<SomethingElse>();
doesn't work:
Cannot implicitely convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
i don't actually need the full List<T> object, just an ICollection<T> will do:
ICollection<SomethingElse> second = first;
ICollection<SomethingElse> second = (ICollection<SomethingElse>)first;
ICollection<SomethingElse> second = first.Cast<SomethingElse>();
don't work.
LINQ, as implemented through the extension methods within the Enumerable class, relies on deferred execution:
Methods that are used in a query that returns a sequence of values do not consume the target data until the query object is enumerated. This is known as deferred execution.
Cast<T> does not create a new list immediately, but rather stores all the information that is required to perform the action. The list would only get enumerated when required (for example, through a foreach statement).
In your case, if you simply intend to iterate over the sequence, you should consider sticking to the IEnumerable<T> interface, which is the declared return type of Cast<T>:
IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
foreach (SomethingElse se in second)
{
// ...
}
This is efficient, since it only performs the cast as each item is iterated.
If you’re convinced you want a new list to be created immediately, use ToList:
List<SomethingElse> second = first.Cast<SomethingElse>().ToList();
Edit: Replying to point posted in comment:
It depends on what you mean by “a list that can be modified”. There are several LINQ query operators that will allow you to alter the definition of your query further. For example, if you want to remove all SomethingElse elements whose IsDeleted property is true, you can use the Where operator:
IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
second = second.Where(element => !element.IsDeleted);
If you want to add a sequence of new elements, you can use the Concat operator:
second = second.Concat(anotherCollectionOfSomethingElse);
If you want to sort your sequence in ascending order of ID, use the OrderBy operator:
second = second.OrderBy(element => element.ID);
Each time, we’re applying a query operator over the former definition of our query, and assigning the new (composite) query to our second variable. LINQ would store all your operators in the query definition. Then, when the sequence is actually enumerated (for example, through a foreach or ToList), it would give you the composite result of your sequence, with all the query operators applied in order.
As with all cases of deferred execution / lazy evaluation, be careful not to go overboard with this. If, for example, you’re going to apply a Where operator which will reduce the size of your sequence drastically, it might make sense to execute the query eagerly and store the enumerated list instead.
You have the option of using either Cast or OfType. Cast will throw an exception if you cannot cast to the type specified. OfType on the other hand will return only those items in the list that can be cast to the specified type. I would recommend using OfType in your situation.
List<Foo> fooList = myList.OfType<Foo>().ToList();
I think you're close with the Cast<T> expression. The difference is that Cast<T> returns an IEnumerable<T>, not a List<T>.
Try this:
IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
You can get a list by doing something similar:
List<SomethingElse> second = first.Cast<SomethingElse>().ToList();

foreach-ing through a listview and accessing subitems?

I'm having difficulty using a foreach statement with a WinForm ListView control. The following two code blocks demonstrates what I'm trying to do. It works with a for loop, but not a foreach.
foreach(var item in listView.Items){
item. <-Can't access any of the subitems of this item
}
vs
for(int i=0;i<listView.Items.Count;i++){
listView.Items[i].Subitems[1] <- Here I can access the sub items
}
I'm trying to use a foreach loop so I can more easily remove items from the ListView.
You need to specify the type:
foreach(ListViewItem item in listView.Items){
To answer your comments:
This is because most controls' item collections implement the non-generic ICollection (and IEnumerable), see this MSDN entry for ListViewItemCollection for example. Since it doesn't implement the generic ICollection<T> or IEnumerable<T>, the compiler can't guess the type of the items from looking at the collections themselves, so you have to tell it that they're of type ListViewItem instead of using var.
You need to specify the type if the item in the collection explicitly. The var keyword uses type inference in order to determine the type of the variable. In the case of var in a foreach clause, it uses the particular implementation of IEnumerable to determine the type.
If the collection only implements IEnumerable (and not a generic IEnumerable<T>), then var will be object
If the collection implements one generic IEnumerable<T> (say, IEnumerable<int>), then var will be T (in the example here, var would be int)
In your case, ListViewItemCollection does not implement any generic form of IEnumerable<T>, so var is assumed to be object. However, the compiler will allow you to specify a more specific type for the iterator variable if the enumerable only implements IEnumerable, and it automatically inserts a cast to that particular type.
Note that, because there's a casting operator, the cast will fail at runtime if the object is not of that particular type. For instance, I can do this:
List<object> foo = new List<object>();
foo.Add("bar");
foo.Add(1);
foreach(string bar in foo)
{
}
This is legal, but will fail when the iterator reaches the second item, since it is not a string.
You need to have the type of the item - in this case: ListViewItem.
Also, if you're planning to remove items from the collection and are using a foreach loop, you cannot directly remove from the you're looping through - you'd need to add each item to remove to a new collection and remove all items in that collection from the original after the termination of the loop.
Use the beautiful collection caster of LINQ
using System.Linq;
foreach(var item in listView.Items.Cast<ListViewItem>()){
item.BackColor = ...
}

How to know which type to use when use foreach on an IEnumerable type?

I have an object which implements IEnumerable interface. In C#, I can use foreach to iterate all its element. However I am wondering how to determine the type in the foreach loop?
If you have an old style IEnumerable (not IEnumerable<T>) you can usually call .Cast<T> or .OfType<T> to get a strongly typed one to .ForEach<T> over...
If you don't know T then you can call Debug.Write(item.GetType())
If you are using only IEnumerable you have to use object. If you know the real type then you can cast that object.
You can also use the generic IEnumberable and then you won't need to do the cast.
Why don't you try var?
foreach(var item in myEnumerable)
{
...
}
Without having the generic variant of IEumerable there is no nice way of knowing.
You could use the is operator to check first item in enumerable along with different foreach loops but I wouldn't recomend it.
If you are using the non-generic IEnumerable you cannot infer the type of items returned through the interface at compile-time. If you know enough about the object, you may know it only contains a specific type, which means you can (with relative safety) construct a foreach loop with the known type. For example, if you know it only returns strings, you can iterate over the object like so:
foreach(string s in myObject)
{
// Do some operation.
}
Unfortunately, you can return any item from a non-generic IEnumerable. If the IEnumerable returns a float, you will receive an InvalidCastException on the first line.
Worse still, there's nothing to prevent the elements being a variety of types within the same sequence. The object could legally return the following types within one foreach loop.
string
int
float
DateTime
If you don't know from the object's documentation, the only other certain way to know the type of any one item in the loop is to check at runtime.
These are the reasons why it's always preferable to use the generic IEnumerable<T> over IEnumerable when you know your object will only really return one type of value.

Extension Method ConvertAll

What is the proper use of ConverAll ? Will it convert one type to another type?
like
List<int> intList = new List<int>();
intList.Add(10);
intList.Add(20);
intList.Add(30);
intList.Add(33);
var query= intList.ConvertAll(x=>(double)x);
for this i can use cast or OfType<>.
ConvertAll isn't an extension method, it's a real method on List<T> itself.
It returns a new list containing the converted elements. So in your example, the query variable isn't actually a query, it's a List<double>.
Cast and OfType are extension methods that operate on IEnumerable and return an IEnumerable<T>. However they're not suitable for your stated purpose: Cast can convert reference types but cannot convert value types, only unbox them. OfType doesn't perform any conversion, it just returns any elements that are already of the specified type.
ConvertAll will just call your delegate/anonymous method for each element of the list. What this does is entirely up to you.
In the example code you posted, it will attempt to cast each element to a double and return that, which means you'll get a List<Double> in return.
You should not use OfType<T>, since this will filter the elements based on the type, and will only return a different type than the original if it is type compatible due to inheritance or interface implementation.
In other words, .OfType<Double> will return no elements, since none of the ints are also doubles.
ConvertAll is a projection operator and maps most closely to LINQ's Select. LINQ's Cast is a specific projection operator and represents doing what you did [via projection] - or it would (as pointed out in Luke's answer [and comment], which I +1'd) if you weren't converting to a value type.
In general, LINQ has a more complete and well-thought-through set of operators, which makes older stuff like ConvertAll look a bit silly at times [like this]. (or #stoopid :D).
to my knowledge, OfType<T> will only return the elements in the collection that are of the specified type T.
ConvertAll allows you to convert the elements to another type.

Categories

Resources