3.8.2. Тип string
Цей тип оголошує (задає) рядкові дані, які дають можливість працювати з текстом. Оголошення в програмі - звичайне:
тип ім’я_змінної_для_майбутнього_рядка
Наприклад:
string s;
Змінній s можна присвоювати константу (літерал), але на відміну від типу char, константа береться в подвійні лапки, щоб компілятор розрізняв, де символ, а де рядок символів, хоч би і з одного символа.
Наприклад
string s="рядок";
string s="a";
char c='a';
У s і a будуть різні дані, хоч би тому, що вони у відведеній їм пам'яті розміщуються по-різному. Проте це не може бути критерієм. Критерієм може бути той факт, що показує, скільки насправді символів міститься в s і a відповідно. В a ми раніше бачили - один символ, точніше, там знаходиться код символа. А в s? Застосуємо вже відомий нам прийом: вставимо в яку-небудь працюючу програму (у текст, зрозуміло) такі рядки:
string s="a";
int n=s.Length;
Тут Length – це (говоримо доки умовно) функція, що обчислює довжину s.
Поставимо точку зупину програми відразу за другим рядком. Після компіляції і пуску програма зупиниться після рядка int n=s.Length;. Тобто значення n вже сформоване. Наведемо курсор миші на n. І що з’явиться? З’явиться одиниця! Отже, довжина n - теж один символ, як і довжина s. Той, хто вивчав С++, буде в розпачі. У повному. Проте і довжина рядка не може, на жаль, служити показником відмінності в типах char і string.
Подивимося на структуру, скажімо так, елементи пам'яті, в якій розміщається рядок. Знаємо, що в комірці повинні розміщуватися символи з таблиці Unicode. Скільки? Від "нічого" до "скільки хочеш". Коли ми пишемо string s=""; (дві лапки підряд)то в s і буде "нічого". Порожній рядок, як кажуть. Вірогідно, її довжина має бути нулем. Перевіримо це згідно програми вищеописаним способом, задавши рядок string s="";. Дійсно, n=0. А що стосується, "скільки хочеш", то вміст змінної типу string дійсно може динамічно змінюватися у бік збільшення і/або зменшення. Що ж до росту у бік збільшення, то тут можливі тільки технічні обмеження.
Згадаємо тепер, що числові і булеві типи даних не збільшуються і не зменшуються. Скільки їм пам'яті виділено, стільки і залишається за ними. Такі типи називають типами-значеннями. Вони зберігаються в стековій пам'яті програми. За пам'яттю, яку вони займають, стежити особливо не потрібно: вони видаляються з пам'яті у міру того, як завершується робота того блоку, в якому вони оголошені. А ось змінні, які динамічно міняють свої розміри (до таких, як ми бачимо, відноситься тип string) вимагають особливого нагляду за собою і тому розміщуються не в блоці, де вони оголошені, а в спеціальному просторі, який розробники назвали кучею. Типи, дані яких розміщуються в кучі називаються посилальними, через те, що разом зі значеннями, властивими таким типам даних, як набір символів Unicode в string, вони містять і вказівники, т. т. адресу, що зв'язує їх зі своїм місцем в стеку (а в стеку ж зберігаються вказівники на посилальні дані, а їх початок - в керованій кучі), щоб спеціальний механізм очищав кучу від їх присутності, коли в цьому виникне потреба, і куча не переповнювалася. Тому елемент пам'яті для рядка складається з двох частин: власне рядка та адреси його початку в стеку. З посиланнями дуже зручно працювати: якщо ви копіюєте один рядок в інший, то не потрібно переганяти величезне число символів з одного рядка в інший. Досить скопіювати в інший рядок тільки посилання, яке вказує, де знаходяться дані, які, нібито, копіюються з початкового рядка. Ось така різниця (суттєва) між рядком з одного символа і змінною типу char, яка за визначенням складається теж з одного символа.
Для рядків визначені операції порівняння: == (дорівнює), != (не дорівнює), + (зчеплення (конкатенація)).
Наприклад
string a = "hello";
string b = "h";
b = b+"ello"; // Додали значення літерала до вмісту b
Console.WriteLine( a == b ); // Виведення на друк рядка - значення виразу
На екран видасться значення True.
Можна написати:
string s="Добрий" + "ранок";
bool b = (s == "Добрий ранок");
Якщо перевірити згідно програми, отримаємо, що b дорівнює True.
Літерали змінної типу string можна записувати в двох формах: текст брати в лапки і поміщеному в лапки тексту може передувати символ @. Літерал може містити будь-які символи, у тому числі і управляючі послідовності. Наприклад
string a = "\\\u0066\n";
У такому літералі обробляються усі символи, включаючи і управляючі. У літералі ж, якому передує символ @, управляючі символи, не обробляються. Маємо:
string a = "\\\u0066\n Проба";
string b=@"\\\u0066\n Проба";
Результат: a="\f\n Проба", b=\\\u0066\n Проба.