WideString и UnicodeString

b

Предыстория: эпоха AnsiString и вызовы глобализации

В середине 90-х годов Delphi, рожденный в мире однобайтовых кодировок, столкнулся с фундаментальной проблемой: AnsiString, привязанный к системной кодовой странице, был бессилен перед многоязычными приложениями. Возникла потребность в типе, способном единообразно представлять символы любого алфавита. Решением стал WideString — прямая обертка над системным BSTR из COM/OLE, которая использовала 16-битное кодирование UCS-2 (а позже UTF-16). Именно этот тип стал первой ласточкой Unicode-поддержки в Delphi, но его цена была высока: каждый символ требовал два байта, а операции конкатенации и копирования происходили с постоянными вызовами SysAllocStringLen из Windows API, что порождало серьезные накладные расходы. WideString решил проблему совместимости, но не производительности.

Переломный момент: выход Delphi 2009 и рождение UnicodeString

Ключевой поворот произошел в 2009 году, когда CodeGear (ныне Embarcadero) принял радикальное решение: сделать UnicodeString новым фундаментальным строковым типом, заменив им AnsiString в ядре языка. Это не было косметическим обновлением. UnicodeString унаследовал механику подсчета ссылок (reference-counted) и оптимизацию copy-on-write от AnsiString, что дало ему колоссальное преимущество перед WideString в операциях присваивания и передачи параметров. В отличие от WideString, который был «тяжеловесом» из-за постоянных маршаллинговых вызовов, UnicodeString жил по правилам менеджера памяти FastMM. Однако за эту производительность пришлось платить: UnicodeString не является «сырой» копией WideString. Там, где WideString гарантировал нулевой терминатор по стандарту COM, UnicodeString мог его не содержать без явного приведения к PChar, что породило волну ошибок при передаче строк в старые Windows API.

Контекст эволюции: почему WideString не умер

Наивно было бы полагать, что появление UnicodeString сразу похоронило WideString. С конца 2000-х годов сложилась четкая экосистема: UnicodeString стал стандартом для кода внутри Delphi-приложений, но WideString сохранил монополию на границе с OLE/COM-объектами. Любой вызов, требующий BSTR (например, работа с Интернет-Explorer через IWebBrowser2 или передача данных в Microsoft Office), требовал именно WideString. Более того, в контексте многопоточных сценариев выявилась парадоксальная ситуация: из-за отсутствия подсчета ссылок операция копирования WideString в разных потоках не требует блокировок на атомарный инкремент счетчика, что в отдельных высоконагруженных случаях делало его безопаснее, чем UnicodeString. Текущая тенденция 2020-х годов — это осознанное сосуществование: разработчики перестали воспринимать WideString как «просто старую версию UnicodeString», а рассматривают его как специализированный инструмент для взаимодействия с неуправляемым кодом.

Современные вызовы: эмуляция ICU и региональные особенности

С 2016 года в экосистеме Delphi наметился новый тренд: отказ от простого хранения строк в пользу осмысленной работы с Unicode. UnicodeString, будучи UTF-16 под капотом, все еще несет в себе проклятие суррогатных пар (символы вне Basic Multilingual Plane, например, некоторые иероглифы или эмодзи). WideString, с другой стороны, исторически был ориентирован на статический UCS-2. Однако современные сборки Windows (начиная с Windows 10) и эмуляция ICU-функций в Delphi 10.3+ заставили пересмотреть границы применимости обоих типов. Сегодня, в 2026 году, ключевой аспект, почему тема не утратила актуальности, — это миграция легаси-проектов, написанных до 2009 года, где повсеместно использовался AnsiString. Под капотом таких проектов часто скрываются хиты вроде преобразования строк через WideString как промежуточное звено, что приводит к потере производительности и ошибкам в определении длины строки. Грамотная замена на прямой UnicodeString с корректным указанием кодовой страницы при преобразованиях стала отдельной дисциплиной.

Практическая значимость для разработчика 2026 года

Почему сегодня, спустя почти два десятилетия после введения UnicodeString, инженеры до сих пор обязаны помнить о WideString? Ответ лежит в плоскости современного интероперабельного программирования. С ростом популярности кросс-платформенных решений (FireMonkey) и внедрением Delphi в облачные сценарии выяснилось, что на Linux и macOS WideString ведет себя принципиально иначе, так как понятие BSTR там эмулируется через подсчет длины в начале буфера, что убивает его главное преимущество — нативность. Разработчики, которые не осознают эту разницу, сталкиваются с трудноотлавливаемыми утечками памяти при вызовах внешних C-библиотек. Более того, современные компиляторы Delphi (вплоть до версии 12.x) все активнее оптимизируют работу с UnicodeString через встроенные процедуры быстрого копирования, делая разрыв в производительности между ним и WideString в операциях внутри процесса почти десятикратным. Игнорирование этой эволюции — прямой путь к созданию «строковых тормозов» в критических участках кода.

Взгляд в будущее: что готовит 2026 год

Текущая тенденция, наметившаяся в 2024–2025 годах, — это постепенное вытеснение WideString в разряд сугубо утилитарных типов для очень узкого круга задач (взаимодействие с COM-серверами, работа с OLE Drag&Drop). В сообществе Delphi все громче звучат голоса о необходимости ввести новый тип — UTF8String с подсчетом ссылок, который позволит обходить дорогостоящую конвертацию в UTF-16 при работе с веб-сервисами и JSON. Это означает, что UnicodeString и WideString, возможно, перестанут быть главными героями в следующем десятилетии, уступив место принципиально иной модели хранения текста. Пока же ключевой навык разработчика — умение выбирать между ними осознанно, понимая исторический багаж и контекст использования. Эволюция строк в Delphi — это не сухая техническая справка, а живой пример борьбы между производительностью, совместимостью и международными стандартами, где каждое решение имеет цену.

Добавлено: 27.04.2026