55

Is it possible to define an anonymous implementation of IComparer?

I believe Java allows anonymous classes to be defined inline - does C#?

Looking at this code I want to define a custom IComparer inline

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    IComparer<TKey> comparer
)
Vojislav Stojkovic
  • 8,043
  • 4
  • 35
  • 48
Jack Kada
  • 24,474
  • 29
  • 82
  • 106

8 Answers8

59

As indicated in one of the comments below, .Net 4.5 allows this via a static method on the Comparer<> class, e.g. comparing two objects based on the value of a property in the class:

var comparer = Comparer<KilowattSnapshot>.Create( 
        (k1, k2) => k1.Kilowatt.CompareTo(k2.Kilowatt) );

Obviously this can be used inline rather than assigned to a variable.

David Clarke
  • 12,888
  • 9
  • 86
  • 116
16

Even though you can't create anonymous classes that implement interfaces, you can usually use the Comparison Delegate instead of the IComparer Interface in most cases (like sorting, etc.):

Array.Sort(arr, (x, y) => 1);

Also there are some built-in implementations of IComparer like the Comparer Class or the StringComparer Class...

Jaroslav Jandek
  • 9,463
  • 1
  • 28
  • 30
  • 11
    With the upcoming .NET4.5 (Visual Studio 2012) it will be possible to make an `IComparer<>` from a `Comparison<>` lambda arrow by using the new factory method `Comparer<>.Create`. – Jeppe Stig Nielsen Aug 08 '12 at 16:36
  • Only thing is `Comparer<>.Create` is extremely ugly to use, because it can't infer arguments (contrast this with how `Tuple.Create` and `Tuple<>` interact). – skolima Feb 05 '13 at 16:42
14

The .NET framework version 4.5 provides the method Comparer.Create(Comparison) to create comparers based on a specified comparison delegate (which can be a lambda function). However people who are working with earlier versions of .NET will probably need to implement something similar themselves.

apokryfos
  • 38,771
  • 9
  • 70
  • 114
8

No, C# does not currently allow inline interface implementations; although it does allow you to create delegates inline through lambda expressions and anonymous methods.

In your case, I would suggest using a ProjectionComparer that makes it easy to use this feature, such as the one listed here.

Brian
  • 25,523
  • 18
  • 82
  • 173
Ani
  • 111,048
  • 26
  • 262
  • 307
  • 3
    @ChloeRadshaw: Java does allow anonymous inner classes that implement interfaces, but it currently has no first-class function concept (such as delegates). – Ani Mar 13 '11 at 11:16
3

No, this is not possible. However, you can get the default implementation of IComparer<TKey> by Comparer<TKey>.Default. Otherwise you'll need to create a parameterized implementation and use an instance of that.

Femaref
  • 60,705
  • 7
  • 138
  • 176
2

C# does not allow implementing interfaces using anonymous inner classes inline, unlike Java. For simple comparisons (i.e. comparing on a single key), there is a better way to do this in C#. You can simply use the .OrderBy() method and pass in a lambda expression specifying the key.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;


namespace Test{
    public class Test{
        public static void Main(){
            IList<int> mylist = new List<int>();
            for(int i=0; i<10; i++) mylist.Add(i);
            var sorted = mylist.OrderBy( x => -x );
            foreach(int x in sorted)
                Console.WriteLine(x);
        }
    }
}
MAK
  • 26,140
  • 11
  • 55
  • 86
1
Array.Sort(arrayName, (x,y) => string.Compare(x.Name,y.Name,StringComparison.CurrentCulture));
Neuron
  • 5,141
  • 5
  • 38
  • 59
1

Take a look at these 2 SO questions, they tackle essentially the same problem

Use of Distinct with list of Custom Object

Wrap a delegate in an IEqualityComparer

If you go this way, you should pay special attention to Slaks' comments and Dan Tao's answer about the hashcode implementation

Community
  • 1
  • 1
bottlenecked
  • 2,079
  • 2
  • 21
  • 32