
- •Предисловие
- •Объектная ориентация программ на C#
- •1.1. Типы, классы, объекты
- •1.2. Программа на C#
- •1.3. Пространство имен
- •1.4. Создание консольного приложения
- •Типы в языке C#
- •2.1. Типы ссылок и типы значений
- •2.2. Классификация типов C#
- •2.3. Простые типы. Константы-литералы
- •2.4. Объявления переменных и констант базовых типов
- •Операции и целочисленные выражения
- •3.1. Операции языка C#
- •3.2. Операции присваивания и оператор присваивания
- •3.3. Операции инкремента (++) и декремента (--)
- •3.4. Выражения с арифметическими операциями
- •3.5. Поразрядные операции
- •Выражения с операндами базовых типов
- •4.1. Автоматическое и явное приведение арифметических типов
- •4.2. Особые ситуации в арифметических выражениях
- •4.3. Логический тип и логические выражения
- •4.4. Выражения с символьными операндами
- •5.2. Простые (базовые) типы C# как классы
- •Операторы
- •6.1. Общие сведения об операторах
- •6.2. Метки и оператор безусловного перехода
- •6.4. Операторы цикла
- •6.5. Операторы передачи управления
- •6.6. Переключатель
- •Массивы
- •7.1. Одномерные массивы
- •7.2. Массивы как наследники класса Array
- •7.3. Виды массивов и массивы многомерные
- •7.5. Массивы массивов и поверхностное копирование
- •Строки – объекты класса string
- •8.1. Строковые литералы
- •8.2. Строковые объекты и ссылки типа string
- •8.3. Операции над строками
- •8.5. Форматирование строк
- •8.6. Строка как контейнер
- •8.7. Применение строк в переключателях
- •8.8. Массивы строк
- •8.8. Сравнение строк
- •8.10. Аргументы метода Main()
- •Методы C#
- •9.2. Соотношение фиксированных параметров и аргументов
- •9.3. Параметры с типами ссылок
- •9.4. Методы с переменным числом аргументов
- •9.5. Перегрузка методов
- •9.6. Рекурсивные методы
- •9.7. Применение метода Array.Sort()
- •Класс как совокупность статических членов
- •10.1. Статические члены класса
- •10.2. Поля классов (статические поля)
- •10.3. Статические константы
- •10.4. Статические методы
- •10.5. Статический конструктор
- •10.6. Статические классы
- •Классы как типы
- •11.1. Объявление класса
- •11.2. Поля объектов
- •11.3. Объявления методов объектов
- •11.4. Пример класса и его объектов
- •11.5. Ссылка this
- •11.6. Конструкторы объектов класса
- •11.7. Деструкторы и финализаторы
- •Средства взаимодействия с объектами
- •12.1. Принцип инкапсуляции и методы объектов
- •12.2. Свойства классов
- •12.3. Автореализуемые свойства
- •12.4. Индексаторы
- •12.5. Индексаторы, имитирующие наличие контейнера
- •Включение, вложение и наследование классов
- •13.1. Включение объектов классов
- •13.2. Вложение классов
- •13.3. Наследование классов
- •13.4. Доступность членов класса при наследовании
- •13.5. Методы при наследовании
- •13.6. Абстрактные методы и абстрактные классы
- •13.7. Опечатанные классы и методы
- •13.8. Применение абстрактых классов
- •Интерфейсы
- •14.1. Два вида наследования в ООП
- •14.2. Объявления интерфейсов
- •14.3. Реализация интерфейсов
- •14.4. Интерфейс как тип
- •14.5. Интерфейсы и наследование
- •Перечисления и структуры
- •15.1. Перечисления
- •15.2. Базовый класс перечислений
- •15.3. Структуры
- •15.4. Упаковка и распаковка
- •15.5. Реализация структурами интерфейсов
- •Исключения
- •16.1. О механизме исключений
- •16.3. Свойства исключений
- •16.5. Исключения в арифметических выражениях
- •16.6. Генерация исключений
- •16.7. Пользовательские классы исключений
- •Делегаты и события
- •17.1. Синтаксис делегатов
- •17.2. Массивы делегатов
- •17.3. Многоадресные групповые экземпляры делегатов
- •17.4. Делегаты и обратные вызовы
- •17.5. Анонимные методы
- •17.6. События
- •Литература
- •Предметный указатель

Строки – объекты класса string
8.1. Строковые литералы
Для представления текстовой информации в C# используются объекты класса string. Класс string представляет собой один из предопределенных типов языка C#. В .Net Framework этому типу соответствует класс System.String. Один из видов объектов класса string мы уже многократно применяли – это строковые константы, или строковые литералы.
Строковая константа, или строковый литерал, имеет две формы – обычный (регулярный) строковый литерал (regu- lar-string-literal) и буквальный строковый литерал (verbatim- string-literal). До сих пор мы использовали только обычную (регулярную) форму, традиционную для языков программирования. Регулярный строковый литерал – это последовательность символов и эскейп-последовательностей, заключенная в кавычки (не в апострофы). В регулярных строковых константах для представления специальных символов используются те же эскейп-последовательности, которые применяются в константах типа char. Обрабатывая регулярный строковый литерал, компилятор из его символов формирует строковый объект и при этом заменяет эскейп-последовательности соответствующими кодами (символов или управляющих кодов). Таким образом, литералу
"\u004F\x4E\u0045\ttwo"
будет соответствовать строка, при выводе которой на экране текст появится в таком виде:
ONE two
Здесь \u004F – юникод символа `О`, \x4E – шестнадцатеричный код символа `N`, \u0045 – юникод символа `E`, \t - эскейп-последовательность, представляющая код табуляции.
Буквальный строковый литерал начинается с префикса @, за которым в кавычках размещается возможно пустая последовательность символов. Символы такого литерала воспринимаются
Строки – объекты класса string |
121 |
|
|
буквально, т. е. в такой строке не обрабатываются эскейп-после- довательности, а каждый символ воспринимается как таковой.
В результате выполнения оператора:
Console.WriteLine("\u004F\x4E\u0045\ttwo");
на экране появится
\u004F\x4E\u0045\ttwo
Если в буквальном литерале необходимо поместить кавычку, то она изображается двумя рядом стоящими кавычками.
Важно отметить, что буквальный литерал может быть размещен в коде программы на нескольких строках, и это размещение сохраняется при его выводе. В то же время попытка перехода на новую строку с помощью эскейп-последовательно- сти \n в буквальном литерале будет безуспешной.
8.2. Строковые объекты и ссылки типа string
Каждый строковый литерал — это объект класса string. Класс string является типом ссылок. Кроме литералов, можно определить объекты класса string с использованием конструкторов. (Конструктор – специальный метод класса, предназначенный для инициализации объекта класса в процессе его создания.) Конструкторы класса string позволяют инициализировать объ- екты-строки несколькими способами.
Наиболее простая форма создания строки-объекта – применение строкового литерала в качестве инициализирующего выражения.
Пример
string line1="Это строка 1";
После выполнения этого объявления создается ссылка line1 типа string, и она ассоциируется со строковым литералом, который является объектом класса string.
Строковый объект можно создавать, используя массив символов:
char [] car ={'M', 'a', 'c', 'c', 'u', 'в'}; string line2 = new string (car);
122 |
Г л а в а 8 |
|
|
В данном примере определен символьный массив. Представляющая его ссылка car используется в качестве аргумента при обращении к конструктору класса string. Значением создаваемого объекта будет строка "Массив". Чтобы получить строку, содержащую один символ, используется конструктор с парамет- ром типа char.
Пример
string line3 = new string ('W');
line3 представляет строку «W».
Если нужна строка, содержащая последовательность одинаковых символов, то применяется конструктор с двумя параметрами. Первый из них определяет нужный символ, а второй – число его повторений.
Пример
string line4 = new string ('7',3);
В данном случае line4 это ссылка на строку "777".
Второй параметр может быть любым целочисленным выражением, поэтому этот конструктор удобно применять в тех случаях, когда количество повторений символа заранее неизвестно, т. е. зависит от каких-то изменяемых при выполнении программы данных.
Обратите внимание, что среди конструкторов класса string нет конструктора с параметром типа string.
Строковые объекты, как создаваемые с применением конструкторов, так и формируемые для представления строковых литералов, компилятор размещает в куче. Ссылки на строки размещаются в стеке. Размер строки при определении строкового объекта явно не указывается, он определяется автоматически при инициализации. Ни размер строки, ни ее содержимое не могут изменяться после создания строки!!
Если инициализация при объявлении строковой ссылки отсутствует, то ей присваивается значение null, и ее нельзя использовать в выражениях до присваивания ей конкретного значения. Пример ошибки:
string line;
line += "asdfg"; // Ошибка компиляции
Строки – объекты класса string |
123 |
|
|
Кроме явного задания строковых литералов и применения конструкторов для создания строковых объектов, используют метод ToString(). Этот метод определен для всех встроенных типов. Например, значением выражения
242.ToString()
будет строковый объект, содержащий изображение символов целого числа "242".
После выполнения операторов
bool b = 5>4;
strng sb = b.ToString();
значением sb будет строка "True"
8.3. Операции над строками
Строки языка C# предназначены для хранения последовательностей символов, для каждого из которых отводится 2 байта, и они хранятся в кодировке Unicode (как данные типа char). В некотором смысле строка подобна одномерному массиву с элементами типа char. Элементы (символы строки) последовательно нумеруются, начиная с 0. Последний символ имеет номер на 1 меньше длины строки.
Для строковых объектов определена операция индексирования:
строка[индексирующее_выражение]
строка – это ссылка на объект класса string, или литерная строка;
индексирующее_выражение – должно быть целочисленным и не может быть меньше нуля.
Результат выражения с операцией индексирования – символ (значение типа char), размещенный в той позиции строки, номер которой соответствует индексному выражению. Если значение индекса меньше нуля, а также больше или равно длине строки, возникает исключительная ситуация (генерируется исключение).
Выражение с операцией индексирования, примененное к строке, только праводопустимое. С его помощью запрещено (невозможно) изменить соответствующий элемент строки.

124 |
Г л а в а 8 |
|
|
В качестве примера рассмотрим выражение, формирующее символьное представление шестнадцатеричной цифры по её десятичному значению в диапазоне от 0 до 15:
"0123456789ABCDEF"[ind]
Если ind ==13, то значением выражения будет 'D'. Операция присваивания (=) для строк выполняется не так
как для массивов. Когда ссылке с типом массива присваивается значения ссылки на другой уже существующий массив, изменяет только значение ссылки. Массив, как объект, становится доступен для нескольких ссылок.
Операция присваивания для строк приводит к созданию нового экземпляра той строки, на которую ссылается выражение справа от знака операции =. Ранее существовавшая строка никак не ассоциируется с новой ссылкой.
Сказанное иллюстрирует рис. 8.1, на котором приведена схема, соответствующая следующим объявлениям:
char [] aCh = {'Б','и','т'}; char[] bCh = aCh;
string aSt = "Байт"; string bSt = aSt;
Рис. 8.1. Присваивания для ссылок на массивы и строки
Операции сравнения на равенство == и неравенство !=, применяемые к строкам, сравнивают последовательности символов в строках. (Отметим, что для массивов сравниваются значения ссылок.)
Строки – объекты класса string |
125 |
|
|
Значением выражения aSt==bSt будет true.
Конкатенацию строк выполняет операция +. Например, после приведенного определения ссылки aSt выражение
aSt+" состоит из 8 бит"
приведет к формированию строки "Байт состоит из 8 бит". Операция + перегружена и обеспечивает конкатенацию не только двух строк, а также строки и операнда другого типа, значение которого автоматически приводится к типу string. Например, выражение
aSt+" содержит "+8+" бит" формирует строку “Байт содержит 8 бит".
Однако значением выражения aSt+" содержит "+8+aCh
будет строка "Байт содержит 8 System.Char[]".
В этом случае ссылка на массив aCh приводится к обозначению типа символьного массива. (Значением выражения aCh. ToString() является "System.Char[]".)
Операция + как конкатенация имеет тот же ранг, что и операция +, обозначающая сложение арифметических данных. Поэтому значением выражения
aSt+" содержит "+4+4+ " бит" будет строка "Байт содержит 44 бита".
По-видимому, это не то, что ожидали. Но ведь операции одного ранга выполняются слева направо.
8.4. Некоторые методы и свойства класса
String
Хотя мы еще не рассматривали механизм и синтаксис наследования и не умеем конструировать производные классы, но уже сейчас полезно отметить, что класс string есть sealed-класс, т. е. он не может служить базовым для других производных классов.
Наиболее важным свойством класса string является свойство Length, позволяющее получить длину (количество символов) конкретной строки (объекта класса string). Значением выражения "\tБином\u0068".Length будет 7, так как каждая эскейп-последо- вательность представляет только один символ.
126 |
Г л а в а 8 |
|
|
Среди многочисленных методов класса string рассмотрим (и то очень кратко) только некоторые.
int CompareTo() – метод, который сравнивает две строки и возвращает целочисленное значение. Для двух строк S1, S2 результат положительный, если S1>S2, отрицательный, если S1<S2, и нулевой, если S1==S2. Сравнение строк выполняется лексикографически.
static string Concat() – метод (их несколько) выполняет конкатенацию строк-параметров. Аргументов-строк может быть два, три или произвольное количество.
static string Copy() – статический метод возвращает копию существующей строки.
static string Format() – статический метод, формирующий строку на основе набора параметров. Этот метод подробно рассматривается в разделе 8.5.
int IndexOf() – нестатический метод поиска в вызывающей строке подстроки, заданной параметром. Возвращает индекс или 1, если поиск неудачен. Поиск – с начала строки.
string Insert() – нестатический метод для вставки строкипараметра в копию вызывающей строки с позиции, заданной дополнительным параметром.
static string Join() – статический метод, объединяющий в одну строку строки массива–параметра. Первый параметр типа string задаёт разделитель, которым будут отделены друг от друга в результирующей строке элементы массива.
int LastIndexOf() – нестатический метод поиска в вызывающей строке подстроки, заданной параметром. Возвращает индекс или -1, если поиск неудачен. Поиск с конца строки.
string Remove() – удаляет символы из копии строки. string Replace() – заменяет символы в копии строки.
string [] Split() – формирует массив строк из фрагментов вызывающей строки. Параметр типа char[] задаёт разделители, которыми в строке разделены фрагменты.
char [] ToCharArray() – копирует символы вызывающей строки в массив типа char[].
string Trim() – удаляет вхождение заданных символов (например, пробела) в начале и в конце строки.
string Substring() – выделяет из строки подстроку. Параметры задают начало и длину выделяемой части строки.
Строки – объекты класса string |
127 |
|
|
8.5. Форматирование строк
При выводе, например, с помощью Console.Write(), значений базовых типов (например, int или double) они автоматически преобразуются в символьные строки. Если программиста не устраивает автоматически выбранный формат их внешнего представления, он может его изменить. Для этого можно воспользоваться статическим методом Format класса string или использовать так называемую строку форматирования в качестве первого параметра методов, поддерживающих форматирование, например, Console.Write() и Console.WriteLine(). В обоих случаях правила подготовки исходных данных для получения желаемого результата (новой строки) одинаковы. Рассмотрим эти правила применительно к методу класса string:
public static string Format(string form, params object[] ar).
Так как синтаксис заголовков методов (функций) мы формально еще не рассматривали, поясним элементы приведенного заголовка.
public – модификатор доступа. Указывает, что метод открытый, т.е. доступен вне класса string.
static – модификатор, относящий метод к классу в целом, а не к его объектам.
string – тип возвращаемого методом значения. Format – имя метода.
form – параметр, представляющий строку форматирования. params – модификатор, указывающий, что следующий за ним массив-параметр ar может быть заменен при обращении к функции любым количеством аргументов (включая нуль, т.е.
аргументы могут отсутствовать).
object – тип элементов массива-параметра ar. Так как object
– это базовый класс для всех типов языка C#, то аргументы, соответствующие элементам массива object[] ar, могут иметь любой тип.
Итак, метод string.Format() возвращает строку, построенную на основе строки форматирования и значений аргументов, следующих за этой строкой в обращении к методу Format().
Строка форматирования включает неизменяемые символы и конструкции, называемые полями подстановок. Структура поля подстановки: {N[,W][:S[R]]}, где N – номер аргумента;
128 |
Г л а в а 8 |
|
|
W - ширина поля; S - спецификатор формата; R – спецификатор точности.
Квадратные скобки в поля подстановки не входят и обозначают необязательность ограниченного ими фрагмента (элемента) поля. В поле подстановки разрешено опускать все элементы, кроме фигурных скобок и номера аргумента. Именно поэтому все остальные элементы поля подстановки мы ограничили квадратными скобками. Воспользуемся этим правилом, чтобы привести первый пример.
int num = 23, den = 6;
string result, // Ссылка на строку, с результатом form = "Числитель: {0}, знаменатель: {1}, дробь: {0}/ {1}=={2}";
result = string.Format(form, num, den, num / den); Console.WriteLine(result);
В примере определены две ссылки result и form на объекты типа string. Значение строки, связанной со ссылкой form, определено инициализирующей строковой константой. В ней пять полей подстановок. Номера в полях указывают, символьные представления значений каких (по счету, начиная с 0) аргументов будут подставлены вместо соответствующих полей. В обращении к методу Format() первый аргумент – строка form, затем num – аргумент, с номером 0, den – аргумент, которому соответствует номер 1, num/den – выражение, значение которого воспринимается как аргумент с номером 2. В результате выполнения подстановок метод Format() возвращает строку, ссылка на которую присвоена переменной result. Выводя эту строку на консоль, получим:
Числитель: 23, знаменатель: 6, дробь: 23/6==3
(Обратите внимание на округление результата целочисленного деления.)
В приведенном примере поля подстановок содержали только номера аргументов. Разберем назначение других элементов, которые в поле подстановки необязательны. Запятая и следующее за ним число (W – ширина поля) в поле подстановки определяет количество позиций, выделяемых для изображения подставляемого значения. Если эти элементы (запятая и
Строки – объекты класса string |
129 |
|
|
число) опущены, то число позиций определяется изображением выводимого значения, т. е. ширина поля выбирается минимально достаточной для изображения значения. Если ширина поля указана, и превышает длину помещаемого в поле значения, то при положительной длине поля W значение выравнивается по правой границе. Если перед шириной поля W стоит минус, то выравнивание выполняется по левой границе поля.
Спецификатор формата S задаёт вид изображаемого значения. Для разных типов данных этот спецификатор выбирается по-разному. Следующая за ним цифра – спецификатор точности R – влияет на формируемое значение, и это влияние зависит от спецификатора формата.
|
|
Таблица 8 . 1 . |
Спецификаторы формата S и точности R |
||
|
|
|
Спецификатор S |
Название формата |
Роль спецификатора |
|
|
точности R |
С или с |
Валютный |
Количество десятичных |
|
|
разрядов |
D или d |
Целочисленный |
Минимальное число |
|
|
цифр |
E или e |
Экспоненциальный |
Число разрядов после |
|
|
точки |
F или f |
С фиксированной |
Число разрядов после |
|
точкой |
точки |
G или g |
Короткий из E или F |
Подобен E или F |
X или x |
Шестнадцатеричный |
Минимальное число |
|
|
цифр |
Пример
double dou = 1234.567;
string form = "Спецификация Е4: {0:E4}, спецификация
F4: {0:F4}";
string result = string.Format(form, dou); Console.WriteLine(result);
В обоих полях подстановки строки форматирования опущена ширина поля, и предполагается дважды использовать только один аргумент (с номером 0).