TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.76K subscribers
Post #1740 1.37K
День 1408. #ЗаметкиНаПолях #TipsAndTricks
Современные Приёмы в C#. Часть 3. Окончание
Часть 1
Часть 2
Часть 3. Начало

Пример применения
В кодовой базе бывают области, где определённые аргументы метода всегда являются константами. Обычно это указывает на то, что метод следует разделить на два, но это не всегда возможно. Возьмём популярный костыль с булевым аргументом, отвечающим за синхронное или асинхронное исполнение метода:
private async Task<string> GetCoreAsync(bool sync)
{
if (sync)
Thread.Sleep(TimeSpan.FromSeconds(1));
else
await Task.Delay(TimeSpan.FromSeconds(1));
return "Hi!";
}

public string Get() =>
GetCoreAsync(true).GetAwaiter().GetResult();

public Task<string> GetAsync() =>
GetCoreAsync(false);

Допустим, что GetCoreAsync намного длиннее и сложнее, и создание двух разных методов действительно усложнит обслуживание.

Воспользуемся обобщённой генерацией кода для создания двух разных методов:
Извлечём различия в коде (Thread.Sleep и Task.Delay). Для них потребуется определение в интерфейсе, и они будут реализованы для каждого типа-значения. Поскольку код может быть синхронным или асинхронным, мы будем использовать ValueTask в качестве типа результата. GetCoreAsync может просто вызывать эти методы интерфейса:
private interface IDelay
{
static abstract ValueTask
DelayAsync(TimeSpan delay);
}

private readonly struct SyncDelay : IDelay
{
public static ValueTask
DelayAsync(TimeSpan delay)
{
Thread.Sleep(delay);
return new();
}
}

private readonly struct AsyncDelay : IDelay
{
public static async ValueTask
DelayAsync(TimeSpan delay) =>
await Task.Delay(delay);
}

private async Task<string> GetCoreAsync<TDelay>()
where TDelay: struct, IDelay
{
await TDelay.DelayAsync(TimeSpan.FromSeconds(1));
return "Hi!";
}

public string Get() =>
GetCoreAsync<SyncDelay>()
.GetAwaiter().GetResult();

public Task<string> GetAsync() =>
GetCoreAsync<AsyncDelay>();

Основная реализация (GetCoreAsync) упрощена и более очевидна. Публичный интерфейс (Get и GetAsync) вообще не изменился. И во время выполнения, если используется только один путь, то только один путь будет скомпилирован JIT-компилятором. Если используются оба пути, JIT создаст две копии GetCoreAsync, каждая из которых оптимизирована для своей ситуации (асинхронной или синхронной). Это особенно полезный метод для библиотек, которым может потребоваться предоставлять обе формы методов, но существует высокая вероятность использования только одного из них.

Стивен Тауб рассказывает в недавнем посте, как BCL использует эту технику.

Примечания и Ограничения
Используя дженерики C# с типами-значений, мы можем обеспечить мономорфизацию, однако остальная часть поведения не гарантируется. JIT не гарантирует, что какие-либо конкретные методы будут встроены или что произойдет какая-либо оптимизация. Разумно предположить, что она будет иметь место, а при современной многоуровневой оптимизации можно также ожидать, что метод станет более оптимизированным, если вызывается много раз.

Вы ограничены только тем, что может быть выражено в виде членов интерфейса. Вы можете определять методы и свойства, но не константные значения или вложенные типы.

Источник: https://blog.stephencleary.com/2022/10/modern-csharp-techniques-3-generic-code-generation.html
  • 👍 3
More from @netdeveloperdiary
  1. Oct 13, 2026День 2813. #ЗаметкиНаПолях #Async Ещё Раз Про Async/Await в C#. Часть 1 1. Почему существу…
  2. Oct 12, 2026День 2812. #Карьера #AI Как Разработчикам Оставаться Полезными, Когда Код Пишет ИИ? По мер…
  3. Oct 11, 2026День 2811. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  4. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  5. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  6. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
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 →