Why does List<T> not implement IOrderedEnumerable<T>?
Asked Answered
A

2

13

I would like to work with ordered enumerables, and use interfaces as return types rather than the concrete types. I need to return an ordered set of objects. But, when using an IList<T> implementation I can not return IOrderedEnumerable<T>, as IList<T> does not inherit IOrderedEnumerable<T>.

In the example below I have a view model with a repository of series, implemented as a List<T> of series objects, which are, as they are residing in a List<T>, ordered. I an accessor method, I want to return a filtered set of the series where only series objects of a specific type are returned, while keeping the original order among the filtered elements.

/// <summary>
/// Represents the view model for this module.
/// </summary>
public class ViewModel : AbstractViewModel
{
    /// <summary>
    /// Gets the series repository.
    /// </summary>
    /// <value>The series repository.</value>
    public IList<ISeries> SeriesRepository { get; private set; }

    //...
}

//8<-----------------------------

    /// <summary>
    /// Gets the series of the specified type.
    /// </summary>
    public IOrderedEnumerable<T> Series<T>() where T : ISeries
    {
        return ViewModel.SeriesRepository.OfType<T>(); //compiler ERROR
    }

The compiler tells me:

Error   14  Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<T>' to 'System.Linq.IOrderedEnumerable<T>'. An explicit conversion exists (are you missing a cast?) ...

How can I support such a scenario? And why does List not implement IOrderedEnumerable?

EDIT: To clarify my intentions: I simply want to declare at the interface level, that my Repository has an order, even if it is not explicitly specified by a key. Thus, .ThenBy et.al. should not add a new order, as there is already one - my own one and only one. :-). I see, that like so, I miss the intention of .ThenBy.

Aeon answered 25/3, 2011 at 8:12 Comment(0)
L
17

How could List<T> implement IOrderedEnumerable<T>? It would have to provide a way of creating a subsequent ordering... what does that even mean?

Consider this:

var names = new List<string> { "Jon", "Holly", "Ash", "Robin", "William" };
var ordered = names.ThenBy(x => x.Length);

what does that even mean? There's no primary sort order (as there would be if I used names.OrderBy(x => x)), so it's impossible to impose a secondary sort order.

I suggest you try creating your own implementation of IOrderedEnumerable<T> based on a List<T> - as you attempt to implement the CreateOrderedEnumerable method, I think you'll see why it's inappropriate. You may find my Edulinq blog post on IOrderedEnumerable<T> useful.

Laylalayman answered 25/3, 2011 at 8:20 Comment(4)
.ThenBy should just add no secondary order, it should just return the original sequence. I see that this misses the idea of it.Aeon
@Marcel: Exactly - you just can't implement it in a meaningful way. That's why it doesn't implement it.Laylalayman
I would say that a List<T> is ordered by the indices of the items inside it. Hence it is only logical that ThenBy would not change anything because there are no equals as defined by the original ordering.Renaerenaissance
Damn, it took me a while to get this but this is right. The problem is that List is ordered arbitrarily (you could say its insert order), while IOrderedEnumerable has a defined sort order, as if it was just ordered via some sorting function.. Perhaps it should be called ISortedEnumerableComplicated
E
9

Well, you are wrong: List<T> is NOT ordered by a particular key. The elements inside the list are in the order you put them in. That's the reason, why List<T> doesn't implement IOrderedEnumerable<T>.
Just return the following:

ViewModel.SeriesRepository.OfType<T>().OrderBy(<your order predicate>);
Effuse answered 25/3, 2011 at 8:17 Comment(8)
@Daniel: I would say a List<T> is ordered: as you say, they're "in the order you put them in". That's an ordering, but it's not an ordering where it makes any sense to impose a "secondary" ordering.Laylalayman
@Jon: My understanding is different. An ordered enumeration is one, that is always ordered by a key, independent of the order the elements have been inserted into the list.Effuse
-1: As the OP, I would like to emphasize that the "order I put them in" is exactly the order I do need, even if there is no explicit key. In the example, the repository's order would be intentionally created.Aeon
@Daniel: That's the meaning of IOrderedEnumerable, yes, but it's not the meaning of the word "ordered" in general. Imagine we weren't talking about LINQ - it would be entirely reasonable to say "One difference between HashSet<T> and List<T> is that the list is ordered, but the set isn't." If you iterate over the list, you know the order in which the values will be returned. Just changing your description to "is not ordered by any particular key" would make it clearer.Laylalayman
@Marcel: So what would you expect the results of calling ThenBy to be? That's the bit you still haven't made clear.Laylalayman
@Marcel: Your downvote teaches me to not try helping you again. After all, I provided you with an explanation why it isn't working and a way around it. @Jon: Updated my answer as suggested. The different understanding might come from the fact that I am not a native speaker. But it looks like even the MS engineers are seeing "order" and "sort" as equivalent. IOrderedEnumerable <-> SortedList <-> OrderBy etc...Effuse
@Daniel: The downvote originally was meant to disagree with "not ordered", but with the update suggested by Jon, your post is clear to me.Aeon
Where does it say that an IOrderedEnumerable<T> has to be ordered by a particular key?Renaerenaissance

© 2022 - 2024 — McMap. All rights reserved.