Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.docx
Скачиваний:
15
Добавлен:
02.11.2018
Размер:
626.37 Кб
Скачать

2.4. Преобразование информации

Платформа .NET и языки программирования, построенные на её основе, предлагают богатый набор средств для решения задачи преобразования информации в данные различных типов.

Язык C# поддерживает операции явного и неявного преобразования типов, причём эти операции могут быть перегружены в пользовательских типах. При этом желательно, чтобы перегружаемые операции преобразования имели простую семантику и работали на сходных множествах значений.

Для выполнения взаимных преобразований данных базовых типов1 предназначен статический класс System.Convert. Этот класс содержит набор методов вида ToИмяТипа(), где ИмяТипа является именем CLR для базовых типов. Каждый такой метод перегружен и принимает аргумент любого базового типа. Выполнение метода может быть успешным или генерировать исключения InvalidCastException, FormatException, OverflowException.

byte x = Convert.ToByte("123"); // x = 123

bool y = Convert.ToBoolean(10.5); // y = true

int z = Convert.ToInt32(DateTime.Now); // InvalidCastException

Класс Convert также содержит методы для взаимных преобразований массива байт в строку (или массив символов) в формате Base-64:

var data = new byte[5] {10, 240, 100, 3, 90};

Console.WriteLine(Convert.ToBase64String(data)); ); // CvBkA1o=

var buffer = Convert.FromBase64String("ax2s732k");

Отметим, что для унификации операций преобразования все базовые типы явным образом реализуют интерфейс System.IConvertible. Это интерфейс содержит набор методов ToИмяТипа(), где ИмяТипа ‑ имя CLR для базовых типов. Каждый такой метод принимает параметр типа IFormatProvider. При реализации IConvertible базовые типы просто вызывают соответствующие методы класса Convert.

Статический класс System.BitConverter содержит набор методов для преобразования переменной числового или булевского типа в массив байт, а также методы обратного преобразования. Подобные преобразования полезны при низкоуровневой работе с потоками данных:

byte[] data = BitConverter.GetBytes(10567);

int x = BitConverter.ToInt32(data, 0);

Важными видами преобразований являются получение строкового представления объекта и получение объекта из строки. Для получения строкового представления объекта можно использовать виртуальный метод ToString(), определённый в классе System.Object. Однако часто требуется предоставить возможность выбора формата представления и учесть региональные стандарты. Для этой цели предназначен интерфейс System.IFormattable, который реализуют числовые типы, структура DateTime, класс Enum и некоторые другие типы:

public interface IFormattable

{

string ToString(string format, IFormatProvider formatProvider);

}

Параметр format – это строка, сообщающая способ форматирования объекта. Многие типы различают несколько строк форматирования. Например, DateTime поддерживает: строку "d" ‑ для дат в кратком формате, "D" ‑ для дат в полном формате, "G" ‑ для дат в общем формате, "M" ‑ в формате «месяц/день», "T" ‑ для времени и т. д. Все числовые типы поддерживают: "C" ‑ для валют, "D" ‑ для десятичных, "E" ‑ для научных, "F" ‑ для чисел с фиксированной точкой, "G" ‑ общий формат, "P" ‑ для процентов, "X" ‑ для шестнадцатеричных чисел. Числовые типы также поддерживают шаблоны форматирования, которые позволяют методу ToString() отобразить нужное количество цифр, место разделителя дробной части, количество знаков в дробной части и т. д. (полную информацию о строках форматирования смотрите в справке MSDN).

Региональные стандарты влияют на форматирование чисел, дат и времени. При формировании строки метод IFormattable.ToString() анализирует параметр formatProvider. Если он равен null, метод определяет региональные стандарты, связанные с текущим потоком выполнения, используя свойство Thread.CurrentThread.CurrentCulture с типом CultureInfo. Получив объект CultureInfo, ToString() считывает его свойства NumberFormat для форматирования числа или DateTimeFormat ‑ для форматирования даты (свойства имеют тип NumberFormatInfo и DateTimeFormatInfo соответственно1). NumberFormatInfo описывает группу свойств NegativeSign, CurrencyDecimalSeparator, CurrencySymbol, NumberGroupSeporator и т. п. Аналогично, у типа DateTimeFormatInfo имеются свойства Calendar, DayNames, DateSeparator, LongDatePattern, ShortTimePattern, TimeSeparator и т. п.

Параметр formatProvider имеет тип IFormatProvider:

public interface IFormatProvider

{

object GetFormat(Type formatType);

}

Реализация интерфейса IFormatProvider означает, что тип знает, как обеспечить учет региональных стандартов при форматировании. Метод ToString() вызывает IFormatProvider.GetFormat(), чтобы получить нужный объект для форматирования числа или даты2. Тип CultureInfo реализует IFormatProvider. Если нужно форматировать строку, скажем, для Вьетнама, следует создать объект CultureInfo и передать этот объект методу ToString():

DateTime dt = DateTime.Now;

// s = "07 Tháng Giêng 2010"

string s = dt.ToString("D", new CultureInfo("vi-VN"));

Если нужно получить строку, которая не отформатирована в соответствии с конкретными региональными стандартами, используется инвариантная культура, доступная через статическое свойство CultureInfo.InvariantCulture.

Чаще всего при получении строкового представления объекта нужно указать только формат, довольствуясь региональными стандартами, связанными с вызывающим потоком. Для упрощения работы во многие типы добавлены перегруженные версии метода ToString(), вызывающие IFormattable.ToString() с параметрами по умолчанию:

int x = 1024;

string s = x.ToString();

s = x.ToString("D3");

s = x.ToString(CultureInfo.InvariantCulture);

s = x.ToString("X", new CultureInfo("vi-VN"));

Тип может содержать дополнительные методы для получения строкового представления данных. Например, в DateTime определены методы ToLongDateString(), ToShortDateString(), ToLongTimeString(), ToShortDateString().

Для получения данных типа по строке обычно используются статические методы, которые по соглашению об именовании называются Parse() и TryParse(). Если преобразование из строки невозможно, метод Parse() генерирует исключение, а TryParse() возвращает значение false. Методы Parse() и TryParse() есть во всех примитивных типах, классе Enum, в типах для работы со временем и многих других типах. Обычно данные методы имеют перегруженные версии, принимающие в качестве параметра IFormatProvider. Некоторые типы дополнительно перегружают Parse() и TryParse() для более тонкой настройки преобразования:

int x = Int32.Parse("1024");

int z = Int32.Parse("A03", NumberStyles.HexNumber);

int y;

if (Int32.TryParse("4201", out y))

{

Console.WriteLine("Success");

}

DateTime dt = DateTime.Parse("13/01/2000 16:45:06");

В заключение рассмотрим вопрос преобразования строк. Платформа .NET способна поддерживать различные текстовые кодировки и наборы символов. Для этого используется базовый класс System.Text.Encoding и наследники этого класса – конкретные кодировки. Чтобы получить объект-кодировку можно использовать статический метод Encoding.GetEncoding() или статические свойства для наиболее популярных кодировок:

// используется имя кодировки по стандарту IANA (www.iana.org)

Encoding utf8 = Encoding.GetEncoding("utf-8");

// распространённую кодировку можно получить через свойство

Encoding ascii = Encoding.ASCII;

Основными методами каждого объекта-кодировки являются GetBytes() и GetString(). Первый метод служит для перевода строки или массива символов в массив байт (коды символов), второй метод делает обратное преобразование:

Encoding ascii = Encoding.ASCII;

byte[] asciiBytes = ascii.GetBytes("Sample text");

string s = ascii.GetString(asciiBytes);