0

I have an abstract class named Time, then two subclasses SingleYear and Period. I could have more subclasses later on.

The Time class implements IComparable, but the CompareTo function is actually implemented in each subclass.

I have a query in linq, like this: myListOfObjects.OrderBy(o=>o.Time);

That is working. However, I'd like to be able to choose whether SingleYear or Period objects should come first (before the actual CompareTo). My implementation of CompareTo is correct, however in some cases I need to show first Periods, then Single Years (or vice-versa).

Since I can have more (let's say 5-6) subclasses, how am I able to specify which subclasses should come first, then CompareTo will do it's work afterwards?

igorjrr
  • 790
  • 1
  • 11
  • 22

3 Answers3

4
.OrderBy(o => o is SingleYear).ThenBy(o => o.Time);
AlexD
  • 32,156
  • 3
  • 71
  • 65
0

I think this would do it:

list.OrderBy(t => typeof(t).Name).ThenBy(o => o.Time)
Maurice Reeves
  • 1,572
  • 13
  • 19
0

In most cases the point of having classes and subclasses is that we can cast them as a base class (or interface) and no longer have to distinguish between specific types.

If you sort these in a way that is aware of the type and you have five or six types then you're eventually going to end up with this:

.OrderBy(o => o is SingleYear)
    .ThenBy(o => o is Period)
    .ThenBy(o => o is SomeOtherClass)
    .ThenBy(o => o is Another)
    .ThenBy(o => o is Whatever)
    .ThenBy(o => o is Etc)
    .ThenBy(o => o.Time);

It's not the end of the world but I wouldn't like it. It's better if we don't differentiate between classes in our code (inspecting to see what type they are.) Instead, classes differentiate themselves by implementing properties and methods differently.

Does the sort order depend on the length of the period? You could have your classes implement a property that indicates the length of a period - perhaps that's constant for SingleYear but calculated for Period.

Then you could either implement IComparable on each class or provide a separate IComparer<T> implementation, like

public class TimeComparer : IComparer<Time>
{
    public int Compare(Time t1, Time t2)
    {
        var periodComparison = t1.Duration.CompareTo(t2.Duration);
        return periodComparison != 0 ? periodComparison : t1.Time.CompareTo(t2.Time);
    }
}
Scott Hannen
  • 27,588
  • 3
  • 45
  • 62