I am using extension methods OrderBy and ThenBy to sort my custom collection on multiple fields. This sort does not effect the collection but instead returns and IEnumberable. I am unable to cast the IEnumerable result to my custom collection. Is there anyway to change the order of my collection or convert the IEnumerable result to my custom collection?
No there isn't. When you use the query operators, it doesn't use instances of the original collection to generate the enumeration. Rather, it uses private implementations (possibly anonymous, possibly not) to provide this functionality.
If you want it in your original collection, you should have a constructor on the type which takes an IEnumerable<T>
(or whatever your collection stores, if it is specific) and then pass the query to the constructor.
You can then use this to create an extension method for IEnumerable<T>
called To<YourCollectionType>
which would take the IEnumerable<T>
and then pass it to the constructor of your type and return that.
No. You could follow the pattern established by the ToList and ToDictionary extension methods - write a similar extension method to load up your own collection type from IEnumerable.
You could write your own instance of IComparer to be able to sort your custom collect.
Brute force you could loop through the IEnumerable and dump each item back into a new instance of your custom collection.
You can initialize a list with IEnumerable:
If items is of type IEnumerable, you can create a list like this:
var list = new List<string>(items);
or you could simply call items.ToList():
var list = items.ToList();
What interfaces does your custom collection implement?
If its an IList then you'd be able to do .ToList() on the IEnumerable If its an IDictionary then you'd be able to do .ToDictionary() on the IEnumerable Etc..
to bring it to something more workable for you.
You could write an extension method for IEnumerable to .ToMyCollection() if nothing is similar.
Enumerables and collections are fairly different beasts.
Enumerations only allow to, well, enumerate while collections have index-based accessors, Count-property and the like. To create a collection you will actually have to enumerate the IEnumerable. Typical Collections like List<T> will have a constructor that accept an IEnumerable. Nonetheless, the enumeration will be performed.
If you look in the System.Linq.Enumerable class there are a few extension methods that will aloow you to convert you IEnumerable type to either an Array, ToList
var myEnumerable = this.GetEnumerator();
var array = myEnumerable.ToArray();
var list myEnumerable.ToList();
You could follow this approach and create a custom extension method that will convert to your custom collection
public static CustomCollection<TSource> ToCustomCollection<TSource>(this IEnumerable<TSource> source);
LINQ is cool because it treats the source-collections like this as immutable - it is not modifying them. Using the extension methods simply enumerates them in the alternate order you specify - you are not building a NEW custom list in this way.
I would suggest two options:
- Build a new list yourself based on the results of your LINQ-ing
- Implement sorting capability into your custom collection (or use a nice sortable generic collection as a base) so it can sort in-place.
If your collection type implements IList<T>
(to be able to Add()
to it) you could write an extension method:
public static Extensions
{
public static TColl ToTypedCollection<TColl, T>(this IEnumerable ien)
where TColl : IList<T>, new()
{
TColl collection = new TColl();
foreach (var item in ien)
{
collection.Add((T) item);
}
return collection;
}
}
Do you really need a custom collection type at all? It sounds like everything you want to do with this is provided by the existing generic collection types, and maybe you just need to add an extension method or to for them.