tags:

views:

34

answers:

2

Suppose I have a method to return a list of keys in a dictionary, sorted by their values:

/// Perhaps a wildly inefficient way to achieve this!
public static List<K> SortByValues<K,V>( Dictionary<K,V> items )
{
    var keys = new K[items.Count];
    var values = new V[items.Count];
    var index = 0;

    foreach( var kvp in items )
    {
        keys[index] = kvp.Key;
        values[index++] = kvp.Value;
    }

    Array.Sort( values, keys );

    return new List<K>( keys );
}

I would like to offer an overload that accepts an IComparer to pass to the Array.Sort method. Is there any way to do this without duplicating all of the code? Ideally there'd be some way to get at the "default" comparer for the type V.

A: 

It looks like you're trying to discover way to get a default value for an IComparer<V> for a given generic parameter V. If so then you are looking for the Comparer<T>.Default property (or EqualityComparer<T> if doing straight equality).

With that it hand you can use the following pattern for accepting custom comparers.

public static List<K> SortByValues<K,V>( Dictionary<K,V> items) {
  return SortByValues(items, Comparer<V>.Default);
}

public static List<K> SortByValues<K,V>( 
   Dictionary<K,V> items, 
   IComparer<V> comparer) {
  ...
}
JaredPar
+1  A: 

Like Comparer<V>.Default, maybe?

You could just change SortByValues to take an IComparer<V> argument and then have an overload call that method passing Comparer<V>.Default:

public static List<K> SortByValues<K,V>(Dictionary<K,V> items) 
{
    SortByValues(items, Comparer<K>.Default);
}

public static List<K> SortByValues<K,V>(Dictionary<K,V> items, IComparer<K> comparer) 
{ 
  var keys = new K[items.Count]; 
  var values = new V[items.Count]; 
  var index = 0; 

  foreach( var kvp in items ) 
  { 
    keys[index] = kvp.Key; 
    values[index++] = kvp.Value; 
  } 

  Array.Sort( values, keys, comparer ); 

  return new List<K>( keys ); 
} 
Stephen Cleary
That was it, thanks for the reference.
Thomas H