tags:

views:

1647

answers:

4

When using linq and you have

c.Sort()

Is there any good inline way of defining a Comparison and/or IComparer class without actually having to create a separate class?

+7  A: 

That's one of the use of lambda expressions:

c.Sort( (x,y) => x.A.CompareTo(y.A))

EDIT: Fixed example to return int (using CompareTo) instead of bool

ckarras
I don't think this will work for IComparer as the lamda should return int rather than bool.
Daniel Ballinger
You are right. This works for IComparison, not for IComparable. Spend the better part of an hour trying to get something like this to work with the NUnit CollectionAssert.IsOrdered method only to figure out that it doesn't.All of the documentation and articles are confusing because they use the sort method as an example. The sort method has overloads that take either IComparer and IComparison. This only works with the sort method because of the IComparison overload.
Brett
+4  A: 

I have a ProjectionComparer class in MiscUtil, so you can do:

IComparer<Foo> comparer = ProjectionComparer<Foo>.Create(x => x.Name);
c.Sort(comparer);

The code is also in this answer.

You can create a Comparison<T> instance directly with a lambda expression too, but I don't generally like the duplication that involves. Having said which, it often ends up being somewhat shorter...

Jon Skeet
I don't get your last 2 sentences. Could you elaborate a tiny bit? Cheers...
flq
Well, if you look at the accepted answer, it's got redundant information: the "A" part is specified twice. (It also won't compile because it returns a bool instead of an int, but never mind.) That's okay if it's a single simple property, but becomes more of a pain if it's a complicated expression.
Jon Skeet
+5  A: 

I've no idea what c.Sort() is in your example, as it can be many things (do you mean List<T>.Sort()?), but one thing that it sure isn't is LINQ. LINQ doesn't have 'Sort() - it has OrderBy()`.

That said, the latter also works with IComparer, and there's no way to create an instance of anonymous class implementing the interface "inline", so you'll have to define a class.

For List<T>.Sort(), there is an overload which takes Comparison<T>. Since it's a delegate type, you can use a lambda to provide the function inline:

List<int> xs = ...;
xs.Sort((x, y) => y - x); // reverse sort
Pavel Minaev
Your right that's not linq - too late in the afternoon
Daniel
"there's no way to create an instance of anonymous class implementing the interface inline" - That depends on your language. F# can do this just fine.
Joel Mueller
@Joel: the language is clearly specified in the tags to the question.
Pavel Minaev
Of course it is. There's also a difference between "no way to do it" and "no way to do it in C#".
Joel Mueller
When answering a question which specifies language X for code, both question and answer imply "... in language X", unless explicitly stated otherwise.
Pavel Minaev
+1  A: 

If the objects in the List c already implement IComparable you wont need another one. But if you need custom comparison, you can implement IComparer in a nested class. You also can use a lambda expression to create a Comparison method on the fly:

persons.Sort( (person1, person2) => person1.Age.CompareTo( person2.Age ) );

codymanix