TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.77K subscribers
Post #363 947
День триста двенадцатый. #DesignPatterns
Паттерны проектирования
1. Паттерн «Стратегия» (Strategy). Окончание
Интерфейс vs. Делегат
Поскольку некоторые стратегии содержат лишь один метод, в .Net часто вместо классической стратегии на основе наследования можно использовать стратегию на основе делегатов. Иногда эти подходы совмещаются, что позволяет использовать наиболее удобный вариант.
Классическим примером такой ситуации является стратегия сортировки, представленная интерфейсом IComparable<T> и делегатом Comparison<T>:
class Employee {
public int Id { get; set; }
public string Name { get; set; }
…
}
// функтор, реализующий интерфейс
class EmployeeByIdComparer : IComparer<Employee> {
public int Compare(Employee x, Employee y) {
return x.Id.CompareTo(y.Id);
}
}

// используем функтор
list.Sort(new EmployeeByIdComparer());
// используем делегат
list.Sort((x, y) => x.Name.CompareTo(y.Name));

По сравнению с использованием лямбда-выражений, реализация интерфейса требует больше кода и приводит к переключению контекста при чтении (необходимости посмотреть реализацию функтора). При использовании метода List.Sort есть возможность использовать оба варианта, но так бывает не всегда, например в случае с классами SortedList или SortedSet:
var comparer = new EmployeeByIdComparer();
// Конструктор принимает IComparable
var set = new SortedSet<Employee>(comparer);
// Нет конструктора, принимающего делегат Comparison<T>

В этом случае можно создать небольшой адаптерный фабричный класс, который будет принимать делегат Comparison<T> и возвращать интерфейс IComparable<T>:
class ComparerFactory {
public static IComparer<T> Create<T>(Comparison<T> comparer) {
return new DelegateComparer<T>(comparer);
}
private class DelegateComparer<T> : IComparer<T> {
private readonly Comparison<T> _comparer;
public DelegateComparer(Comparison<T> comparer) {
_comparer = comparer;
}
public int Compare(T x, T y) {
return _comparer(x, y);
}
}
}
Теперь, используя этот класс, можно создать функтор из лямбда-делегата:
var comparer = ComparerFactory.Create<Employee>((x, y) => x.Id.CompareTo(y.Id));
var set = new SortedSet<Employee>(comparer);

Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 1.
More from @netdeveloperdiary
  1. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  2. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  3. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
  4. Oct 7, 2026День 2807. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Окончание Нач…
  5. Oct 6, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
  6. Oct 6, 2026День 2806. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Начало Больши…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →