Здравствуйте, G-Host, Вы писали:
GH>Довольно часто приходится передавать IComparer<> в разные методы.
GH>Для пользовательских классов приходится создавать класс, наследовать и т.п., да еще и хранить ссылку на экземпляр отдельно
GH>чтобы то и дело не было создания.
GH>Когда намного проще было бы написать лямбду "на месте".
Был такой замечательный советский фильм про конструкторов ракет (начинавших ещё в довоенные годы). Так там вот один такой "молодой" конструктор приходит к двум уже "заматеревшим" и показывает свои чертежи. А те смотрят и спрашивают: "Шестой вариант уже поди?" — "а откуда вы знаете" — "А вот когда тридцатый (тут точную цифру забыл я) сделаешь, сам поймёшь"
Далее сначала добавляется ещё один (Convert) "самый полезный метод":
public static partial class Comparers
{
public static Comparer<T> Create<T>(Comparison<T> comparison) {
Argument.NotNull(comparison, "comparison");
return new ComparisonComparer<T>(comparison);
}
public static Comparer<TOutput> Convert<TInput, TOutput>(this IComparer<TInput> comparer, Converter<TOutput, TInput> converter) {
Argument.NotNull(comparer, "comparer");
Argument.NotNull(converter, "converter");
Comparison<TOutput> comparison = (x, y) => comparer.Compare(converter(x), converter(y));
return Create(comparison);
}
[Serializable]
private sealed class ComparisonComparer<T> : Comparer<T>
{
public ComparisonComparer(Comparison<T> comparison) {
Argument.NotNull(comparison, "comparison");
Comparison = comparison;
}
private Comparison<T> Comparison { get; set; }
[ContractInvariantMethod]
private void Invariant() {
Contract.Invariant(Comparison != null);
}
public override int Compare(T x, T y) {
return Comparison(x, y);
}
}
}
| Потом другой: |
| public static partial class Comparers
{
public static Comparer<T> Reverse<T>(this IComparer<T> comparer) {
Argument.NotNull(comparer, "comparer");
return new ReverseComparer<T>(comparer);
}
public static Comparer<T> DefaultReverse<T>() {
return ReverseComparer<T>.Default;
}
[Serializable]
private sealed class ReverseComparer<T> : Comparer<T>
{
private static readonly ReverseComparer<T> @default = new ReverseComparer<T>(Comparer<T>.Default);
public ReverseComparer(IComparer<T> comparer) {
Argument.NotNull(comparer, "comparer");
Original = comparer;
}
public static new ReverseComparer<T> Default {
[DebuggerStepThrough]
get { return @default; }
}
private IComparer<T> Original { get; set; }
[ContractInvariantMethod]
private void Invariant() {
Contract.Invariant(Original != null);
}
public override int Compare(T x, T y) {
return Original.Compare(y, x);
}
}
}
|
| |
| Третий… |
| public static partial class Comparers
{
public static Comparer<T> ThenBy<T>(this IComparer<T> first, IComparer<T> second) {
Argument.NotNull(first, "first");
Argument.NotNull(second, "second");
return new ThenByComparer<T>(first, second);
}
[Serializable]
private sealed class ThenByComparer<T> : Comparer<T>
{
public ThenByComparer(IComparer<T> first, IComparer<T> second) {
Argument.NotNull(first, "first");
Argument.NotNull(second, "second");
First = first;
Second = second;
}
private IComparer<T> First { get; set; }
private IComparer<T> Second { get; set; }
[ContractInvariantMethod]
private void Invariant() {
Contract.Invariant(First != null);
Contract.Invariant(Second != null);
}
public override int Compare(T x, T y) {
var value = First.Compare(x, y);
if(value == 0) {
return Second.Compare(x, y);
}//if
return value;
}
}
}
|
| |
| Ну и до кучи |
| public static partial class Comparers
{
public static bool Equals<T>(this IComparer<T> comparer, T left, T right) {
Argument.NotNull(comparer, "comparer");
return comparer.Compare(left, right) == 0;
}
public static bool NotEquals<T>(this IComparer<T> comparer, T left, T right) {
Argument.NotNull(comparer, "comparer");
return comparer.Compare(left, right) != 0;
}
public static bool LessThan<T>(this IComparer<T> comparer, T left, T right) {
Argument.NotNull(comparer, "comparer");
return comparer.Compare(left, right) < 0;
}
public static bool LessThanOrEqual<T>(this IComparer<T> comparer, T left, T right) {
Argument.NotNull(comparer, "comparer");
return comparer.Compare(left, right) <= 0;
}
public static bool GreaterThan<T>(this IComparer<T> comparer, T left, T right) {
Argument.NotNull(comparer, "comparer");
return comparer.Compare(left, right) > 0;
}
public static bool GreaterThanOrEqual<T>(this IComparer<T> comparer, T left, T right) {
Argument.NotNull(comparer, "comparer");
return comparer.Compare(left, right) >= 0;
}
}
|
| |
А остальное уж совсем экзотика
Тут полезно что: наружу выдаётся не IComparer<>, а Comaprer<>, качественное отличие которого в том, что он так же реализует и не-дженерик IComparer и его можно использовать в больше количестве сценариев и даётся это совершенно забесплатно.
Метод Convert позволяет отсортировать, например, коллекцию бизнес-объектов по какому-либо полю, а ThenBy по совокупности полей.