23284
Все самое полезное для C#-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/b60af5a4 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
⚡️ .NET 10 Blazor: как выбрать render mode для реального проекта
Blazor даёт три модели выполнения. Это не стилистические различия — они определяют где живёт память, как работает сеть и во сколько обходится масштабирование.
Interactive Server
C# выполняется на сервере, браузер — тонкий клиент. Между ними — постоянный WebSocket: каждое UI-событие летит на сервер, обратно возвращается только diff DOM.
Каждая открытая вкладка создаёт circuit в памяти сервера. 1000 пользователей — ~300 МБ только на состояние, 20 000 — уже серьёзная инфраструктура.
Зато можно инжектить DbContext прямо в компонент, не нужен API-слой, скорость разработки максимальная. Подходит для внутренних инструментов с небольшой аудиторией.
Interactive WebAssembly
Браузер скачивает .NET runtime и сборки приложения, C# выполняется локально. UI-события не уходят в сеть — отклик мгновенный.
Сервер становится stateless: только API и статика.
Первая загрузка тяжелее — от 2 до 10+ МБ в зависимости от сборок. И главное правило: никаких секретов в WASM, IL декомпилируется.
Вся авторизация и бизнес-логика — только за API. Хорошо масштабируется, дёшево хостится через CDN.
Interactive Auto
Гибридный режим: первый визит работает как Server — мгновенный рендер без ожидания загрузки WASM. Параллельно браузер скачивает рантайм, и при следующем визите компонент уже выполняется на клиенте.
Сложность в том, что один и тот же компонент должен уметь работать в обоих контекстах. Прямой @inject AppDbContext сломается в браузере.
Решение — общий интерфейс с двумя реализациями: серверной и клиентской. DI сам подставит нужную.
Как выбирать:
— небольшая внутренняя аудитория, нужна скорость разработки → Server
— публичный SaaS, много пользователей, важна стоимость хостинга → WebAssembly
— публичное приложение, важен SEO и первый paint, но нужна SPA-производительность → Auto
— сложный продукт с разными модулями → комбинируйте режимы под каждый раздел
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#sharp_view
✏️ Оставить след в опенсорсе
goodfirstissue.dev собирает задачи с пометкой good first issue из популярных проектов — это реальные баги и небольшие фичи, которые мейнтейнеры специально отмечают как подходящие для новичков в проекте.
Контрибьют в open-source — это не только строчка в резюме. Это код-ревью от людей, которые написали библиотеки, которыми мы пользуемся, и понимание того, как устроены проекты изнутри.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#sharp_view
💡 Подборка вакансий для шарпистов
Senior разработчик C# — удалёнка
Middle/Middle+ C#/.NET Developer — тоже удалёнка
.NET-разработчик — от 250 000 ₽ и снова удалёнка
➡️ Еще больше топовых вакансий — в нашем канале C# Jobs
🐸 Библиотека шарписта
👀 YAGNI в реальной жизни
YAGNI (You Aren't Gonna Need It) — принцип из разработки: не делайте то, что может пригодиться когда-нибудь. Работает не только в коде.
Не покупайте инструмент на всякий случай. Нужна дрель — возьмите в аренду или одолжите. Купите перфоратор — будет пылиться 10 лет.
Не записывайтесь на 5 курсов параллельно, «пройду потом» может не случится — вдруг смените род деятельности, к примеру. Закончите один, потом решайте нужен ли следующий.
💬 Бывало такое, что нарушали YAGNI в реальной жизни? Или может наоборот трезво оценили ситуацию и не купились? Интересно будет почитать в комментах 👇
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#entry_point
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#garbage_collector
🧑💻 Юнит-тестирование F# с xUnit
Рассмотрим, как настроить юнит-тестирование F#-библиотеки с помощью xUnit и dotnet test.
Для чистоты разделим библиотеку и тесты на два отдельных проекта внутри одного solution:
/unit-testing-with-fsharp
unit-testing-with-fsharp.sln
/MathService ← бизнес-логика
/MathService.Tests ← тесты
mkdir unit-testing-with-fsharp && cd unit-testing-with-fsharp
dotnet new sln
mkdir MathService && cd MathService
dotnet new classlib -lang "F#"
cd ..
dotnet sln add ./MathService/MathService.fsproj
module MyMath =
let private isOdd x = x % 2 <> 0
let private square x = x * x
let squaresOfOdds xs =
xs
|> Seq.filter isOdd
|> Seq.map square
mkdir MathService.Tests && cd MathService.Tests
dotnet new xunit -lang "F#"
dotnet reference add ../MathService/MathService.fsproj
cd ..
dotnet sln add ./MathService.Tests/MathService.Tests.fsproj
dotnet reference add доступна в .NET 10+. На более ранних SDK используйте dotnet add reference.module MathService.Tests
open Xunit
[<Fact>]
let ``Sequence of Evens returns empty collection`` () =
let expected = Seq.empty<int>
let actual = MyMath.squaresOfOdds [2; 4; 6; 8; 10]
Assert.Equal<Collections.Generic.IEnumerable<int>>(expected, actual)
[<Fact>]
let ``Sequences of Ones and Evens returns Ones`` () =
let expected = [1; 1; 1; 1]
let actual = MyMath.squaresOfOdds [2; 1; 4; 1; 6; 1; 8; 1; 10]
Assert.Equal<Collections.Generic.IEnumerable<int>>(expected, actual)
[<Fact>]
let ``SquaresOfOdds works`` () =
let expected = [1; 9; 25; 49; 81]
let actual = MyMath.squaresOfOdds [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
Assert.Equal(expected, actual)
🤑 Мы ждали этого несколько месяцев
Что вы будете делать в этот дополнительный выходной?
Полная раскайфовка на кровати или жёсткий пет-проектинг?
💬 Пишите в комментах 👇
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#entry_point
⚡ AI-агенты в экосистеме .NET: строим надёжный Production в 2026 году
Интеграция нейросетей в корпоративные системы требует не только знания API, но и понимания процессов логирования, трассировки и юридической чистоты. Мы полностью обновили курс по AI-агентам, сделав упор на управляемость и архитектурный подход.
📚 В обновлённой программе:
— инжиниринг качества: измерение метрик производительности и устранение регрессий;
— промышленный RAG: продвинутые подходы к обработке разнородных документов;
— human-in-the-loop: встраивание человека в критические узлы принятия решений;
— юридические аспекты: детальное руководство по использованию 152-ФЗ.
Начните учиться уже сейчас — материалы для предварительной подготовки доступны сразу после регистрации.
⏳ Специальные условия до 28 февраля:
— введите промокод Agent для получения скидки 10 000 рублей**;
— участвуйте в **акции «3 курса по цене 1» — выберите два любых курса в дополнение к основному.
👉 Получить доступ к курсу и подаркам
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#garbage_collector
❓ Что не так с кодом
В коде спрятан намёк на обновление, которое принёс нам C# 10 версии. Может публичные поля? Или конструктор.. Явно что-то связанное со структурой.
👉 Ответ 👈
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#dotnet_challenge
👩💻 Гендерный разрыв в IT
Женщины в IT получают на 40% меньше мужчин — и первый порыв объяснить это дискриминацией. Но если копнуть в данные, картина усложняется. Разрыв формируется ещё в вузе, продолжается в выборе специализации и усиливается декретом.
➡️ Разбираем, где именно ломается воронка
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
👨💻 Конец эпохи State Machine
Все мы знаем и любим async/await. Но знаете ли вы, что под капотом происходило всё это время?
Каждый раз когда вы писали async метод — компилятор переписывал его в большой конечный автомат. Вместо вашего чистого кода генерировался struct, реализующий IAsyncStateMachine, с MoveNext(), switch-блоками и кучей вспомогательных полей.
Microsoft перенесла управление async из компилятора прямо в рантайм. Теперь компилятор больше не генерирует конечный автомат — он просто помечает метод атрибутом [MethodImpl(MethodImplOptions.Async)] и делает шаг назад.
Рантайм сам перехватывает await-точки через AsyncHelpers.Await(...), сохраняет только нужные переменные и возобновляет выполнение когда Task готов.
Что это даёт:
• Zero allocation в happy path — никакого лишнего боксинга
• Читаемые стектрейсы с вашими именами методов, а не MoveNext
• Рантайм понимает async-семантику и может оптимизировать цепочки await
• Native AOT поддержка из коробки
Как включить сейчас:
<Features>$(Features); runtime-async=on</Features>
<EnablePreviewFeatures>true</EnablePreviewFeatures>
<TargetFramework>net11.0</TargetFramework>
🧩 API Gateway в .NET
API Gateway — это единая точка входа, которая берёт на себя маршрутизацию, аутентификацию, rate limiting и агрегацию запросов. Клиент общается с одним адресом — Gateway сам разбирается, куда слать запрос.
Ocelot vs YARP
Ocelot — классика жанра. Конфигурируется через JSON, прост в старте:
{
"Routes": [{
"UpstreamPathTemplate": "/api/orders/{id}",
"DownstreamPathTemplate": "/orders/{id}",
"DownstreamHostAndPorts": [{"Host": "orders-svc", "Port": 80}]
}]
}builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
app.MapReverseProxy(pipeline => {
pipeline.UseAuthentication();
pipeline.UseAuthorization();
});
Интегрируем AI в .NET экосистему
Бизнес требует внедрения AI, но не в виде игрушки, а как надёжного сервиса. Мы пересобрали курс «Разработка AI-агентов», сделав упор на промышленные стандарты и архитектуру.
В программе:
🔹 От демо к инжинирингу. Управление ресурсами, кэширование, роутинг и контроль затрат (FinOps для AI).
🔹 RAG нового уровня. Пайплайны для работы с «грязными» данными, таблицами и корпоративными базами знаний.
🔹 LangGraph PRO. Управляемые графы состояний, time-travel для отладки и возможность отката действий.
🔹 Юридический контур. Развёртывание решений с учётом 152-ФЗ.
Стартуй сейчас! Материалы пре-подготовки доступны сразу.
🎟 Промокод Agent — скидка 10 000 ₽ (до 28 февраля).
👉 Инженерный подход к AI
🤩 Microsoft раскрыла планы по развитию PowerShell и OpenSSH
Пока Microsoft работает над устранением болевых точек Windows 11, компания параллельно вкладывается в инструменты для опытных пользователей.
PowerShell 7.7 станет центральным обновлением года. Среди ключевых изменений: профили и модули переедут из папки Documents в более подходящее место, появится возможность загружать модули без правки профиля, отложенные уведомления об обновлениях для пакетных менеджеров, поддержка псевдонимов и макросов в стиле Bash, а также собственный MCP-сервер.
Windows OpenSSH может получить поддержку аутентификации через EntraID.
➡️ Источник
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
🤖 GitHub Copilot Testing для .NET теперь в Visual Studio 2026
Microsoft официально выпустила инструмент для автоматической генерации юнит-тестов прямо в IDE. Больше не нужно писать тесты с нуля вручную.
Вы пишете в Copilot Chat @Test и описываете, что хотите протестировать. И Copilot сам:
— генерирует юнит-тесты
— собирает и запускает их
— находит упавшие тесты и пытается их починить
— повторяет, пока всё не стабилизируется
— показывает итоговый отчёт: покрытие до/после, что прошло, что упало
Что можно просить:
@Test покрой тестами мою бизнес-логику
@Test класс OrderService, целевое покрытие 80%
@Test напиши тесты для моих текущих изменений в git
@Test используй xUnit и FluentAssertions
За год мы провели три потока курса по ИИ-агентам, а теперь запускаем масштабное обновление!
В новом, четвёртом потоке мы учли все пожелания студентов, добавили большой блок про AgentOps и сместили фокус с базовых концепций на суровый инжиниринг. Сделать простую цепочку на C
легко, а вот интегрировать агентов в корпоративный контур, чтобы они не галлюцинировали и не сливали бюджет в проде — задача со звёздочкой.
В программе:
— интеграции по стандарту MCP и мультиагентные паттерны;
— оркестрация в LangGraph: human-in-the-loop и runbook для отказов;
— продвинутый RAG для промышленной эксплуатации и парсинг сложных документов;
— контроль экономики агентов: маршрутизация и кеширование;
— развёртывание локальных опенсорс-моделей в закрытых контурах по 152-ФЗ.
В честь старта продаж действует спецпредложение: 3 курса по цене 1 (два дополнительных курса в подарок).
Доступ к материалам для предварительной подготовки откроется сразу после оплаты.
По промокоду Agent забирайте скидку 10 000 ₽ (89 000 ₽ вместо 99 000 ₽). Успейте занять место до 28 февраля!
👉 Присоединиться к четвёртому потоку и вывести агентов в прод
🔗 Идём в нативный мир
Иногда .NET-коду нужно выйти за пределы управляемого мира и напрямую поговорить с операционной системой, нативными библиотеками или COM-компонентами. Для этого существует Native Interop — набор механизмов, встроённых прямо в рантайм.
Зачем это вообще нужно
Три основных сценария: ОС предоставляет огромное количество API, которых нет в BCL, например, доступ к оборудованию, системные вызовы; интеграция с кодом на C/C++ или Java через JNI; и автоматизация Windows-приложений вроде Office через COM.
Platform Invoke — главный инструмент
Platform Invoke позволяет вызывать функции из нативных библиотек .dll / .so / .dylib. В .NET 7+ вместо старого [DllImport] рекомендуется использовать [LibraryImport]:
[LibraryImport("nativelib", EntryPoint = "to_lower",
StringMarshalling = StringMarshalling.Utf16)]
internal static partial string ToLower(string str);LibraryImport запускает source-генератор, который формирует весь код маршалинга на этапе компиляции, а не в рантайме — это открывает возможность для Native AOT и инлайнинга P/Invoke-вызовов.[MarshalAs] и [StructLayout]. Для нативных структур нужно воспроизвести их в управляемом коде с точным совпадением порядка и размеров полей.
👨💻 TDD в больших проектах
Все слышали мантру: «пиши тесты сначала, код потом». Звучит разумно. Но когда проект уже большой, то TDD может занять куда больше сил.
Казалось бы, вот простая задача: добавить поле DeliveryComment к заказу. Бизнес просит, задача на час.
Давайте по TDD — сначала тест:
[Fact]
public void CreateOrder_WithDeliveryComment_ShouldPersistComment()
{
var service = new OrderService(...); // 6 зависимостей
var request = new OrderRequest { DeliveryComment = "Позвонить за 10 минут" };
var result = service.CreateOrder(request);
Assert.Equal("Позвонить за 10 минут", result.DeliveryComment);
}
// OrderRequest.cs
public string? DeliveryComment { get; set; }
// OrderEntity.cs
public string? DeliveryComment { get; set; }
// OrderService.cs
entity.DeliveryComment = request.DeliveryComment;
👨💻 Задача, которую переписывают снова и снова
Каждый, кто работал с ASP.NET Core хоть на одном серьёзном проекте, знает этот момент: надо отправить письмо, SMS или пуш — и начинается. Подключаете SendGrid, пишете обёртку, потом прилетает задача «добавь ещё Slack», потом WhatsApp, потом Teams.
Каждый раз — новый провайдер, новый SDK, новый слой абстракции, который придумывается на ходу.
С такой болью была написана библиотека RecurPixel.Notify, которая закрывает эту проблему.
Идея простая: один интерфейс INotifyService — любой канал. Email, SMS, Push, WhatsApp, Slack, Discord, Teams, Telegram, Facebook, Viber и даже In-App нотификации. Всё через одну точку входа, всё через стандартный DI.
Подключается в одну строку:
dotnet add package RecurPixel.Notify.Sdk
👨💻 Блокнот теперь с картинками
Российские пользователи Notion, которых в 2022 году попросили на выход, могут выдохнуть — замена найдена.
Microsoft методично превращает Блокнот во всё то, за что люди платили подписку: таблицы уже есть, ИИ уже есть, Markdown уже есть, картинки вот-вот завезут.
Поддержка изображений тестируется во внутренних сборках, и по результатам тестов функция практически не влияет на производительность.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
📰 Дайджест недели
Без лишних слов
— Microsoft раскрыла на PowerShell и OpenSSH
— Новая фича C#
— Конец эпохи State Machine
— Гендерный разрыв в IT
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
🤨 Переходить на .NET 10 или нет
.NET 10 вышел в ноябре 2025 года — и это LTS-релиз, то есть Microsoft будет поддерживать его несколько лет. Хорошая база для прода.
Основные изменения крутятся вокруг трёх вещей: производительность, язык и экосистема. JIT-компилятор стал агрессивнее инлайнить вызовы и оптимизировать аллокации, что на CPU-интенсивных и API-нагруженных сценариях даёт до 5–30% прироста на горячих путях.
C# 14 добавил extension members, field-backed properties и ряд мелких улучшений, которые заметно сократят бойлерплейт у авторов библиотек. EF Core тоже стал быстрее на ряде запросов.
Если у вас покрытый тестами прод, нормальный CI и необходимость в долгосрочной поддержке — мигрировать стоит.
План простой: сначала апгрейдите изолированный сервис или библиотеку, снимите замеры P95/P99 и аллокаций до и после, убедитесь что всё работает — и масштабируйте.
Для старта можно использовать официальный инструмент:
dotnet tool install -g upgrade-assistant
upgrade-assistant upgrade MySolution.sln
LLM в корпоративном .NET: от хаоса к управляемой архитектуре
Бизнес массово требует внедрять ИИ в корпоративные системы. Но базовые боты ломаются о реальные задачи, уходят в бесконечные циклы и нарушают политики безопасности.
Мы обновили курс по AI-агентам, сделав упор на enterprise-стандарты 2026 года. Теперь это инженерный гайд по созданию стабильных, измеримых и безопасных систем, которые не страшно пускать в продакшн.
Что мы разбираем на курсе:
— хардкорный RAG: парсинг кривых корпоративных сканов, таблиц и улучшение поисковых запросов;
— оркестрация: маршрутизация, human-in-the-loop для критичных решений и восстановление состояний;
— контроль затрат: детальное управление токенами, кэшем и предотвращение перегрузок;
— автоматизация: управление браузером и интеграция с legacy-продуктами;
— правовой контур: разворачивание решений с соблюдением 152-ФЗ и подготовка документов.
Активируйте промокод Agent до 28 февраля и забирайте скидку 10 000 рублей.
Используя акцию «3 курса по цене 1», вы можете выбрать ещё два курса в подарок.
Построить надёжных AI-агентов
📣 Если C# для вас — это уже не просто язык, а инструмент для построения систем, следующий шаг — научиться проектировать и разрабатывать так, как это делают сильные команды в продакшене.
Курс «C# Developer. Professional» — про Best Practices .NET-разработки и реальную инженерную работу. Вы углубитесь в работу с атрибутами, асинхронность и многопоточность, разберёте паттерны проектирования, работу с SQL и NoSQL, кэширование, CI/CD и тестирование.
❕Программа построена вокруг практики и командной разработки. Вы будете работать в Scrum-команде, проходя весь цикл: от постановки задач до итогового проекта. Преподаватели — практикующие эксперты, программа регулярно обновляется под требования рынка. Это обучение, которое повышает инженерную зрелость и ценность специалиста.
➡️Старт курса - 27 февраля. Курс доступен в рассрочку. Пройдите короткое вступительное тестирование и получите специальные условия на обучение: https://clc.to/bFJJ_g
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
🤩 Regex вместо while-loop
Классический паттерн очистки строк, который встречается в приложениях:
while (text.Contains(" "))
{
text = text.Replace(" ", "");
}Replace() — это полная аллокация новой строки, копирование содержимого и выброс старого объекта на съедение GC. При длинных прогонах повторяющихся символов цикл делает это многократно. Сложность — O(n²), давление на GC — ощутимое.Regex.Replace с квантификатором +:text = Regex.Replace(text, @"-+", "-");
public partial class StringNormalizer
{
[GeneratedRegex(@"-+")]
private static partial Regex ConsecutiveDashRegex();
public static string NormalizeSlug(string input)
=> ConsecutiveDashRegex().Replace(input, "-");
}
[GeneratedRegex] переносит компиляцию паттерна на этап сборки. В рантайме — никакого парсинга, никаких лишних аллокаций при инициализации, валидация паттерна прямо в IDE.
📎 Новая фича C#
В C# 15 появится возможность передавать аргументы в конструктор или фабричный метод коллекции прямо внутри выражения коллекции — через элемент with(...).
Раньше, если нужно было создать List<string> с заданной ёмкостью или HashSet<string> с нестандартным компаратором, приходилось делать это отдельно. Теперь всё пишется в одну строку:
// Задаём начальную ёмкость списка
List<string> names = [with(capacity: values.Length * 2), .. values];
// Передаём компаратор в HashSet
HashSet<string> set = [with(StringComparer.OrdinalIgnoreCase), "Hello", "HELLO", "hello"];
// В set окажется один элемент — все строки равны при OrdinalIgnoreCase
with(...) должен быть первым элементом в выражении коллекции.
📈 Подборка вакансий для шарпистов
.NET-разработчик — от 250 000 ₽, удалёнка
C#/.NET-разработчик — 265 000 ₽, Офис/Гибрид в Екатеринбурге
Middle/Senior .NET Developer — до 3 500 $, удалёнка
➡️ Еще больше топовых вакансий — в нашем канале C# Jobs
🐸 Библиотека шарписта
📎 Парсим HTML в C#
FreeSpire.Doc для .NET — профессиональная библиотека для обработки документов. Она позволяет разработчикам на C# читать, анализировать и извлекать HTML-контент с минимальным количеством кода и без внешних зависимостей.
Установка через NuGet:
Install-Package FreeSpire.Doc
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System;
using System.IO;
using System.Text.RegularExpressions;
string htmlContent = @"
<html>
<body>
<h2>Описание возможностей продукта</h2>
<p>Этот компонент поддерживает<span style='font-size:14px;'> парсинг HTML</span> и имеет следующие преимущества:</p>
<ul>
<li>Кроссплатформенная совместимость .NET</li>
<li>Не зависит от Office</li>
<li>Быстрое извлечение текста</li>
</ul>
</body>
</html>
";
Document parseDoc = new Document();
Section section = parseDoc.AddSection();
Paragraph paragraph = section.AddParagraph();
try
{
// Ключевой метод: загрузка и парсинг HTML
paragraph.AppendHTML(htmlContent);
// Извлечение чистого текста
string pureText = parseDoc.GetText();
// Очистка текста от лишних пробелов
pureText = Regex.Replace(pureText, @"\s+", " ").Trim();
Console.WriteLine("Извлечённый текст:");
Console.WriteLine(pureText);
}
finally
{
parseDoc.Dispose();
}
string htmlFilePath = "sample.html";
Document parseDoc = new Document();
parseDoc.LoadFromFile(htmlFilePath);
// Извлечение заголовков (h1-h6)
foreach (Section sec in parseDoc.Sections)
{
foreach (Paragraph para in sec.Paragraphs)
{
if (para.GetStyle().Name.StartsWith("Heading"))
{
Console.WriteLine(para.Text.Trim());
}
}
}
// Извлечение элементов списков
foreach (Section sec in parseDoc.Sections)
{
foreach (Paragraph para in sec.Paragraphs)
{
if (para.ListFormat.ListType != ListType.NoList)
{
Console.WriteLine(para.Text.Trim());
}
}
}
// Извлечение гиперссылок
foreach (Section sec in parseDoc.Sections)
{
foreach (Paragraph para in sec.Paragraphs)
{
foreach (DocumentObject docObj in para.ChildObjects)
{
if (docObj is Field field && field.Type == FieldType.FieldHyperlink)
{
string linkText = field.FieldText;
string linkUrl = field.GetFieldCode().Split('"')[1];
Console.WriteLine($"Текст: {linkText}, URL: {linkUrl}");
}
}
}
}
using или вызывайте Dispose() для освобождения ресурсов
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#garbage_collector