![]() |
![]() |
![]() |
Пример: класс String
Другим хорошим примером класса с несколькими конструкторами является класс String. Хотя для конструирования строк предусмотрена сокращенная запись (последовательность символов, заключенная в кавычки), в более сложных случаях лучше перейти на использование конструкторов. Например, один из конструкторов создает строку, состоящую из нескольких копий одного символа. Следующая команда создает строку из 37 пробелов:
Dim str As String
= New String((CChar(" "), 37)
В данном
случае вместо конструктора можно воспользоваться функцией Space (учтите, что
в режиме жесткой проверки типов Option Strict On строка, состоящая из одного
символа «пробел», должна преобразовываться в символ специальной
функцией).
Обобщенная
форма этого конструктора выглядит так:
New (ByVal с
as Char, ByVal count As Integer)
При работе
с классом Stri ng также часто используется конструктор New(ByVal val ue() As
Char, который получает массив символов и преобразует их в строку.
Поскольку
строковые переменные в VB .NET стали объектными, при вводе «.» после
имени строковой переменной появляется подсказка IntelliSense со списком членов
класса String.
Чрезвычайно
полезный класс StringBuilder входит в пространство имен System.Text (пространства
имен рассматриваются в следующем разделе). Этот класс следует использовать вместо
обычного класса String в тех случаях, когда вы собираетесь внести постоянные
изменения в строку. Дело в том, что при каждом изменении строки (даже при простом
добавлении нового символа) VB .NET приходится создавать новую строку, а эта
операция требует времени. При работе с экземпляром класса StringBuilder VB .NET
обходится модификацией исходного объекта.
При создании
пустого объекта Stri ngBui I der методом New VB .NET резервирует блок памяти
для 16 символов и автоматически наращивает его при включении новых символов.
Объект StringBuilder можно рассматривать как «интеллектуальный»
массив символов, который увеличивается и уменьшается по мере надобности и поэтому
в каком-то смысле напоминает тип Stri ng в V-B6. Текущий размер объекта Stri
ngBui I der называется вместимостью (capacity). В классе Stri ngBui I der определены
шесть конструкторов, перечисленных в табл. 4.1.
Таблица
4.1. Конструкторы класса StringBuilder
Конструктор |
Описание |
New() |
Вызывается без
параметров. Создает пустой объект StringBuilder с начальной вместимостью
16 символов |
New(ByVal value
As String) |
Создает объект
StringBuilder, исходное состояние которого определяется заданной строкой |
New (ByVal capacity
As Integer) |
Создает пустой
экземпляр, но резервирует место для заданного количества символов
с возможностью дальнейшего неограниченного роста по мере необходимости
(если вы точно знаете минимальный начальный размер строки, этот вариант
эффективнее автоматического увеличения объекта StringBuilder) |
New(ByVal capacity
As Integer, ByVal maxCapacity As Integer) |
Создает пустой
экземпляр, резервирует место для заданного количества символов, но
допускает дальнейший рост только до заданного порога. При попытке
превысить заданное максимальное количество символов инициируется исключение
(см. главу 7) |
New(ByVal value As String, ByVal capacity As Integer) | Создает объект StringBuilder с заданным исходным состоянием и начальной вместимостью |
New(ByVal value As String, ByVal startlndex As Integer, ByVal length As Integer, ByVal capacity As Integer) |
Создает объект
StringBuilder с заданной начальной вместимостью по части строки |
Сколько
времени теряется при создании новых экземпляров строки? Мы провели тестирование
(при этом использовалась программа, приведенная в подразделе «Хронометраж
— насколько быстрее работает класс StringBuilder?» ниже). Оказалось,
что класс StringBuilder обычно работает в сотни раз быстрее, чем класс String.
На практике это соотношение может быть и выше, поскольку в наших тестах не
использовались дополнительные возможности класса StringBuilder, позволяющие
избежать частого выделения памяти. В результате оптимизации класс StringBuilder
может работать еще быстрее. С другой стороны, если вы просто обращаетесь к
отдельным символам строки и не собираетесь изменять ее, обычный класс String
оказывается эффективнее класса StringBuitder.
В следующем
фрагменте показано, как быстро создать строку, состоящую из 25 000 повторений
буквы А:
Dim bar As New
String("A" .25000)
Dim foo As New
System.Text.SthngBuilder(Bar)
Свойство
Chars позволяет прочитать или записать символ, находящийся в заданной позиции
Stri ngBui I der. Индексация начинается с 0, поэтому для экземпляра StringBuilder
с именем foo команда foo.Chars(l) = "b" заменяет второй символ
строки символом «b».
При помощи
свойства Length можно получить или задать текущий размер объекта Stri ngBuilder.
Если указанное значение меньше текущего размера, VB усекает объект Stri ngBuilder.
Если при создании объекта StringBuilder была задана максимальная вместимость,
в случае ее превышения инициируется исключение (исключения рассматриваются в
главе 7).
Часто используемые
члены класса StrlngBuilder очень сильно перегружены. Они существуют в
большом количестве версий, что позволяет выполнять со строками разнообразные
операции — включать и удалять в них строки, символы, массивы символов и т. д.
Например, метод Append добавляет символы в конец объекта
StringBuilder:
Dim foo As New System.Text.StringBuilder()
foo = foo.Append("A")
foo.Appenc("hello")
' Добавляет 5 символов
foo.Append(37)
' Добавляет 2 символа
foo. Append (new
Random()) '??
Как показывает
последняя строка приведенного фрагмента, к объекту Stri ngBui I der можно присоединить
произвольный объект. При этом VB автоматически вычисляет строковое представление
объекта (а точнее, вызывает его метод ToStri ng) и присоединяет полученную строку
к StringBuilder. Конечно, осмысленность строкового представления объекта зависит
от реализации класса. В приведенном примере вместо случайного числа будет добавлена
бесполезная строка System.Random (но команда foo. Append (New Random(). Next
приведет к желаемому результату).
Метод Insert
вставляет объект или значение в заданную позицию объекта
StringBuilder:
Insert(ByVal
index As Integer.ByVal thing As Object)
Похожую сигнатуру
имеет и метод Remove, удаляющий заданное количество символов с заданной позиции:
Remove(ByVal
startlndex As Integer.ByVal length As Integer)
Перегруженные
версии метода Replace выполняют несколько полезных операций:
У этого метода
существуют еще две версии, позволяющие заменить все вхождения заданной подстроки
или символа в заданном фрагменте объекта Stri ngBuilder (параметр count определяет
длину фрагмента):
Repliсе(ByVal
oldChar As Char.ByVal newChar As Char.ByVal startlndex As Integer._ ByVal count
A's Integer)
ReplacefoldValue
As String.ByVal newValue As String.ByVal startlndex As Integer._ ByVal count
As Integer)
В
классе StringBuilder определен метод Equals, но в отличие от строк два объекта
StringBuilder с одинаковым содержимым не обязательно считаются равными. Это
объясняется тем, что в .NET Framework истинное выражение a.Equals(b) должно
оставаться истинным всегда, а для объектов StringBuilder это невозможно, поскольку
они изменяются. Использовать метод Equals для объектов StringBuilder не рекомендуется.
Метод ToStri
ng преобразует объект Stri ngBui1der в String. Это делается лишь после того,
как все необходимые изменения будут внесены и в дальнейшем вы собираетесь только
читать содержимое4 строки.
Хронометраж — насколько быстрее работает класс StringBuilder?
Хотя Microsoft
не разрешает публиковать точные результаты хронометража для бета-версий (и это
вполне разумно, поскольку в них содержится большой объем отладочного кода),
отношение результатов, полученных в ходе измерений, почти всегда остается более
или менее постоянным. Иногда в окончательной версии это отношение слегка изменяется,
но в гораздо меньшей степени, чем абсолютные значения показателей.
Хронометраж
в VB .NET реализуется легко — достаточно объединить метод Now с методом Ticks
класса DateTlme. Как подсказывает само название, метод Now возвращает текущие
показания системных часов. Метод Ti cks возвращает число типа Long, равное количеству
100-наносекундных интервалов, прошедших с 00:00 1 января 0001 года (1 наносекунда
= 1/1 000 000 000 секунды).
Следующая
программа использовалась для оценки того, насколько быстрее класс StringBuilder
выполняет присоединение символов в конец строки по сравнению с классом String.
Выигрыш растет с увеличением количества символов; при 50 000 символов эффективность
возрастала более чем в 800 раз!
Option Strict
On Module Modulel
Sub Main()
Dim i As Integer
Dim StartTime
As New DateTime()
Dim EndTime
As New DateTime()
StartTime =DateTime.Now()
Dim theText
As New System.Text.SthngBuilder()
For i =1 To
50000
theText =theText.Append("A")
Next
EndTime =DateTime.Now
Dim answerl,answer2
As Long
' Количество
100-наносекундных интервалов
answer1 =EndTi
me.Ticks()-StartTime.Ticks()
StartTime =DateTime.Now()
Dim aString
As String
For i =1 To
50000
aString =aString
& "A"
Next
EndTime =DateTime.Now
' Количество
100-наносекундных интервалов
answer2 =(EndTime.Ticks()-StartTime.Ticks())
Console.WriteLine("StringBuilder
was " & _ answer? /answerl & "times faster.")
Console.ReadLine()
End Sub
End Module
![]() |
![]() |
![]() |