patterncsharpMinor
Custom iComparer
Viewed 0 times
customicomparerstackoverflow
Problem
I've got a base class
I sometimes put all my
I wanted to order my list (first by Graph type, then by name) so I implemented my custom
But it seems very verbose and I'd love to make it shorter (also, as it's my first
Example:
Let's take
I put it in the list named
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
Also see https://stackoverflow.com/questions/4287537/checking-if-the-object-is-of-same-type
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.