HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Custom iComparer

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
customicomparerstackoverflow

Problem

I've got a base class GraphUIControl which is inherited by 4 child classes:

  • BubbleGraphUIControl



  • BatchGraphUIControl



  • LineGraphUIControl



  • StackedGraphUIControl



I sometimes put all my GraphUIControl in the same List for some obscure reasons.

I wanted to order my list (first by Graph type, then by name) so I implemented my custom iComparer:

public class GraphUIControlComparer : IComparer
{
    public int Compare(GraphUIControl x, GraphUIControl y)
    {
        if (x.GetType() == y.GetType())
        {
            return String.Compare(x.Parent.Name, y.Parent.Name, StringComparison.Ordinal);
        }
        if (x is BubbleGraphUIControl)
        {
            return -1;
        }
        if (y is BubbleGraphUIControl)
        {
            return 1;
        }
        if (x is BatchGraphUIControl)
        {
            return -1;
        }
        if (y is BatchGraphUIControl)
        {
            return 1;
        }
        if (x is LineGraphUIControl)
        {
            return -1;
        }
        if (y is LineGraphUIControl)
        {
            return 1;
        }
        if (x is StackedGraphUIControl)
        {
            return -1;
        }
        if (y is StackedGraphUIControl)
        {
            return 1;
        }       
        return 0;
    }
}


But it seems very verbose and I'd love to make it shorter (also, as it's my first iComparer, if I made a mistake/nonsense/whatever, don't hesitate to tell me!)
Example:

Let's take A, A1, A2, B & C as :

  • A is a BubblueGraphUIControl



  • A1 is a BubblueGraphUIControl



  • A2 is a BubblueGraphUIControl



  • C is a LineGraphUIControl



  • B is a StackedGraphUIControl



I put it in the list named myList in random mode. When I do myList.Sort(new GraphUIControlComparer()) I want myList to be in the order A, A1, A2, C, B because of the types order following this rule:

  • BubbleGraphUIControl



  • BatchGraphUIControl



  • LineGraphUIControl



  • `StackedGrap

Solution

Under most circumstances, it's a good idea to avoid GetType(). Using it indicates something's wrong with your design. But if you're willing to use it, there's a very interesting way to write this (I won't say it's good, it's just interesting and short):

public class GraphUIControlComparer : IComparer
{
    private int NameCompare(GraphUIControl x, GraphUIControl y)
    {
        return String.Compare(x.Parent.Name, y.Parent.Name, StringComparison.Ordinal);
    }

    private static readonly Dictionary typeLookupDict
      = new Dictionary
      {
         {typeof(BubbleGraphUIControl), 0},
         {typeof(BatchGraphUIControl), 1},
         {typeof(LineGraphUIControl), 2},
         {typeof(StackedGraphUIControl), 3}
      };

    private int TypeLookup(GraphUIControl x)
    {
       return typeLookupDict[x.GetType()];
    }

    public int Compare(GraphUIControl x, GraphUIControl y)
    {
        int tx = TypeLookup(x);
        int ty = TypeLookup(y);
        if (tx == ty)
        {
            return NameCompare(x,y);
        }
        return (tx < ty ? -1 : 1);
    }
}


Also see https://stackoverflow.com/questions/4287537/checking-if-the-object-is-of-same-type

Code Snippets

public class GraphUIControlComparer : IComparer<GraphUIControl>
{
    private int NameCompare(GraphUIControl x, GraphUIControl y)
    {
        return String.Compare(x.Parent.Name, y.Parent.Name, StringComparison.Ordinal);
    }

    private static readonly Dictionary<Type, int> typeLookupDict
      = new Dictionary<Type,int>
      {
         {typeof(BubbleGraphUIControl), 0},
         {typeof(BatchGraphUIControl), 1},
         {typeof(LineGraphUIControl), 2},
         {typeof(StackedGraphUIControl), 3}
      };

    private int TypeLookup(GraphUIControl x)
    {
       return typeLookupDict[x.GetType()];
    }

    public int Compare(GraphUIControl x, GraphUIControl y)
    {
        int tx = TypeLookup(x);
        int ty = TypeLookup(y);
        if (tx == ty)
        {
            return NameCompare(x,y);
        }
        return (tx < ty ? -1 : 1);
    }
}

Context

StackExchange Code Review Q#85780, answer score: 5

Revisions (0)

No revisions yet.