Как правильно писать тесты 46 Цикл разработки 46 Структура проекта с тестами 51 Утверждения (Asserts) 52 Утверждения в форме ограничений 54 Категории 56
Вид материала | Тесты |
СодержаниеМетод ToString() |
- Некорректные задания, 1276.79kb.
- К техническому регламенту, 835.7kb.
- Правительства Российской Федерации от 11 ноября 2005 г. N 679 о порядке разработки, 494.44kb.
- Постановлением Правительства Российской Федерации от 11 ноября 2005 г. N 679 о порядке, 652.85kb.
- Постановлением Правительства Российской Федерации от 11 ноября 2005 г. N 679 о порядке, 623.18kb.
- Правительства Российской Федерации от 11. 11. 2005 N 679 о порядке разработки и утверждения, 533.6kb.
- Постановления Правительства Российской Федерации от 11. 11. 2005 n 679 о порядке разработки, 613.63kb.
- Об утверждении требований к схемам теплоснабжения, порядку их разработки и утверждения, 450.79kb.
- Рабочая программа учебной дисциплины. Общие требования, порядок разработки, согласования, 414.77kb.
- Постановлением Правительства Российской Федерации от 11 ноября 2005 г. N 679 о порядке, 1924.26kb.
Метод ToString()
Метод System.Object.ToString() является одним из наиболее используемых в среде .NET. Необходимо при разработке своего класса переопределять этот метод. В противном случае каждому пользователю класса придется самостоятельно извлекать свойства класса и создавать из них читабельную строку.
Информация о классе в виде строки может быть полезна при использовании Windows Forms, Web forms или при выводе на экран. Кроме того, строковое представление может быть полезно при отладке. При создании сложных классов следует использовать более хитроумный метод IFormattable.ToString(). Помните: если этот метод не будет переопределен или если переопределение будет плохо написано, за разработчиков это придется делать самим клиентам.
Версия метода ToString() из System.Object просто возвращает имя класса. Эта информация бесполезна: ведь "Rect", "Point" или "Size" — вовсе не то, что следует показывать пользователям. Но это именно то, что будут получать пользователи, если в ваших классах не будет переопределен метод ToString(). Класс пишется всего один раз, но использовать его клиентам приходится много раз. Чуть больше работы при написании класса, но это окупится при его применении.
Обсудим самое простое из требований: переопределение System.Object.ToString(). Рассмотрим класс Customer с тремя полями:
public class Customer
{
private string _name;
private decimal _revenue;
private string _contactPhone;
}
Версия из Object.ToString() вернет "Customer". Лучше переопределить метод, чтобы он возвращал хотя бы имя заказчика:
public override string ToString()
{
return _name;
}
Еще одна причина, по которой удобно переопределять этот метод, состоит в том, что .NET FCL использует его при выводе названий объектов, помещенных в визуальные элементы управления (combo boxes, list boxes, text boxes). Этот же метод работает при передаче объекта в методы
System. Console.WriteLine() и System.String.Format().
В приведенном выше типе customer имеются три поля: имя пользователя, его доход и номер контактного телефона. В переопределении System.ToString() применяется только имя заказчика. Эту ситуацию можно исправить, включив в используемый тип реализацию интерфейса IFormattable. В IFormattable содержится метод ToString(), позволяющий задавать для типа форматирующую информацию. Именно этот интерфейс следует применять в тех случаях, когда требуется создать различные формы строкового вывода. Класс customer относится к подобным случаям. Пользователь может захотеть создать отчет, в котором будет в табличной форме содержаться информация об имени заказчика и его доходе за последний год. Метод IFormattable.ToString() предлагает средства, позволяющие форматировать строку, получаемую от метода ToString(). Сигнатура метода IFormattable.ToString() имеет в параметрах строку с форматом и провайдера формата:
string System.IFormattable.ToString( string format, IFormatProvider formatProvider )
С помощью параметра format можно задать собственные форматы для строки, описывающей класс. Можно задать собственные ключевые символы. В примере с customer можно указать, что n означает имя, r — доходы, p — номер телефона. Если разрешить пользователям применение комбинаций символов, можно создать такую версию
#region IFormattable Members
// supported formats:
// substitute n for name.
// substitute r for revenue
// substitute p for contact phone.
// Combos are supported: nr, np, npr, etc
// "G" is general.
string System.IFormattable.ToString( string format,
IFormatProvider formatProvider )
{
if ( formatProvider != null )
{
ICustomFormatter fmt = formatProvider.GetFormat(
this.GetType( ) )
as ICustomFormatter;
if ( fmt != null )
return fmt.Format( format, this, formatProvider );
}
switch ( format )
{
case "r":
return _revenue.ToString( );
case "p":
return _contactPhone;
case "nr":
return string.Format( "{0,20}, {1,10:C}",
_name, _revenue );
case "np":
return string.Format( "{0,20}, {1,15}",
_name, _contactPhone );
case "pr":
return string.Format( "{0,15}, {1,10:C}",
_contactPhone, _revenue );
case "pn":
return string.Format( "{0,15}, {1,20}",
_contactPhone, _name );
case "rn":
return string.Format( "{0,10:C}, {1,20}",
_revenue, _name );
case "rp":
return string.Format( "{0,10:C}, {1,20}",
_revenue, _contactPhone );
case "nrp":
return string.Format( "{0,20}, {1,10:C}, {2,15}",
_name, _revenue, _contactPhone );
case "npr":
return string.Format( "{0,20}, {1,15}, {2,10:C}",
_name, _contactPhone, _revenue );
case "pnr":
return string.Format( "{0,15}, {1,20}, {2,10:C}",
_contactPhone, _name, _revenue );
case "prn":
return string.Format( "{0,15}, {1,10:C}, {2,15}",
_contactPhone, _revenue, _name );
case "rpn":
return string.Format( "{0,10:C}, {1,15}, {2,20}",
_revenue, _contactPhone, _name );
case "rnp":
return string.Format( "{0,10:C}, {1,20}, {2,15}",
_revenue, _name, _contactPhone );
case "n":
case "G":
default:
return _name;
}
}
#endregion
Воспользоваться этим методом можно так:
IFormattable c1 = new Customer();
Console.WriteLine( "Customer record: {0}",
c1.ToString( "nrp", null ) );
Реализация IFormattable.ToString() зависит от конкретного класса, но ряд случаев необходимо обрабатывать в каждой реализации интерфейса IFormattable. Во-первых, необходимо поддерживать общий формат "G". Во-вторых, нужно поддерживать пустой формат в обоих вариантах его задания: "" и null. Все три спецификатора формата должны возвращать ту же самую строку, что и переопределяемый нами метод Object.ToString(). Для каждого типа, в котором реализуется IFormattable, .NET FCL вызывает IFormattable.ToString() вместо Object.ToString(). Обычно .NET FCL вызывает IFormattable. ToString с пустой (null) строкой формата, но в некоторых случаях для указания общего формата используется строка формата "G". Если добавить поддержку интерфейса IFormattable и не обеспечить поддержку этих стандартных форматов, будет нарушено автоматическое преобразование строк в FCL.
Второй параметр в IFormattable.ToString() является объектом, который реализует интерфейс IFormatProvider. Этот параметр позволяет клиентам добавлять не предусмотренные при проектировании опции форматирования. В предложенной выше реализации IFormattable.ToString() отсутствует целый ряд опций форматирования, которые могли бы быть полезны. Рано или поздно пользователю потребуется такой формат, предусмотреть который не удалось. Вот почему в нескольких первых строках метода ищется объект, который реализует IFormatProvider, и выполняется делегирование задания в ICustomFormatter.
Допустим, что потребовался формат, не поддерживаемый на данный момент. Скажем, появились заказчики, чьи фамилии длиннее 20 символов, и нужно модифицировать формат так, чтобы предоставить фамилии заказчика поле размером 50 символов. Здесь необходим интерфейс IFormatProvider. Для получения собственных форматов выходных данных вы создаете класс, в котором реализуется IFormatProvider, и класс-компаньон, в котором реализуется ICustomFormatter. В интерфейсе IFormatProvider определяется один метод: GetFormat(). Этот метод возвращает объект, реализующий интерфейс ICustomFormatter. А этот интерфейс специфицирует метод, который выполняет фактическое форматирование. Следующая пара (классов) создает модифицированные выходные данные, где имени пользователя отводится 50 позиций:
// Example IFormatProvider:
public class CustomFormatter : IFormatProvider
{
#region IFormatProvider Members
// IFormatProvider contains one method.
// This method returns an object that
// formats using the requested interface.
// Typically, only the ICustomFormatter
// is implemented
public object GetFormat( Type formatType )
{
if ( formatType == typeof( ICustomFormatter ))
return new CustomerFormatProvider( );
return null;
}
#endregion
// Nested class to provide the
// custom formatting for the Customer class.
private class CustomerFormatProvider : ICustomFormatter
{
#region ICustomFormatter Members
public string Format( string format, object arg,
IFormatProvider formatProvider )
{
Customer c = arg as Customer;
if ( c == null )
return arg.ToString( );
return string.Format( "{0,50}, {1,15}, {2,10:C}",
c.Name, c.ContactPhone, c.Revenue );
}
#endregion
}
}
Метод GetFormat() создает объект, чей класс реализует интерфейс ICustomFormatter. Метод ICustomFormatter.Format() выполняет всю работу по форматированию.
В ICustomFormatter.Format() можно задать параметры форматирования. В результате объект FormatProvider типа IFormatProvider будет получен из метода GetFormat(). Чтобы задать свой способ форматирования при выводе информации об объекте, нужно передать в метод string.Format() объект типа IFormatProvider:
Console.WriteLine( string.Format( new CustomFormatter(), "", c1 ));
Содержание 1
Процесс разработки программного обеспечения 3
Основные принципы объектно-ориентированного программирования (начало) 12
История 14
Основные принципы объектно-ориентированного программирования (продолжение) 15
Главные понятия 15
Основные принципы 15
Абстракция данных 15
Инкапсуляция 16
Наследование 16
Основные принципы объектно-ориентированного программирования (окончание) 18
Полиморфизм 18
Отношения 19
Основы .NET Framework 22
Введение 22
Обзор выполнения кода в среде CLR 26
Компиляция исходного кода в управляемые модули 26
Части управляемого модуля 28
Объединение управляемых модулей в сборку 29
Загрузка CLR при выполнении программы 31
Исполнение кода сборки 31
IL и верификация 36
Небезопасный код 36
IL и защита интеллектуальной собственности 37
NGen.exe — генератор объектного кода 38
Библиотека классов .NET Framework 38
Общая система типов (Common Type System, CTS) 40
Общеязыковая спецификация 42
Модульное тестирование (unit testing) 44
Предпосылки 44
Преимущества 44
Поощрение изменений 45
Упрощение интеграции 45
Документирование кода 45
Отделение интерфейса от реализации 45
Ограничения 46
Как правильно писать тесты 46
Цикл разработки 46
Структура проекта с тестами 51
Утверждения (Asserts) 52
Утверждения в форме ограничений 54
Категории 56
Настройка среды выполнения тестов 57
Дополнительные утверждения 59
Тесты и исключения 60
Правила тестирования 62
Юнит-тестирование 70
Пример 70
Два вида констант 98
Операторы is, as и приведение типов 101
Метод ToString() 109
Типы-значения и ссылочные типы 117
Неизменяемые (Immutable) атомарные типы-значения 122
0 в типах-значениях 132
Методы ReferenceEquals(), Equals(), статический метод Equals() и operator== 134
Циклы foreach 140
Управление ресурсами в .NET 143
Инициализаторы переменных 149
Инициализация статических полей классов с помощью статических конструкторов 155
Цепочки конструкторов 157
Применение операторов using и try/finally для освобождения ресурсов 160
О минимизации мусора 167
Упаковка и распаковка 169
Наследование классов и реализация интерфейсов 171
Отличие реализации методов интерфейса от переопределения виртуальных методов 178
Введение в паттерны проектирования 184
Что такое паттерн проектирования 186
Паттерны проектирования в схеме MVC 188
Описание паттернов проектирования 190
Каталог паттернов проектирования 192
Как решать задачи проектирования с помощью паттернов 195
Механизмы повторного использования 204
Сравнение структур времени выполнения и времени компиляции 210
Проектирование с учетом будущих изменений 212
Как выбирать паттерн проектирования 220
Как пользоваться паттерном проектирования 221
Делегаты и события 226
Делегаты 226
События 230
Параметры событий 233
Атрибуты 237
Синтаксис 237
Создание атрибута 240
Составляющие класса атрибута 242
Получение значений атрибута 244
Задание 1 245
Задание 2 246
Обобщения 251
Проблемы создания объектных образов и восстановления значений 252
Типовая безопасность и строго типизованные коллекции 253
Проблемы создания объектных образов и строго типизованные коллекции 258
Пространство имен System.Collections.Generic 259
Тип List
Создание обобщенных методов 263
Пропуск параметров типа 265
Создание обобщенных структур (и классов) 267
Ключевое слово default в обобщенном программном коде 269
Создание пользовательских обобщенных коллекций 271
Установка ограничений для параметров типа с помощью where 274
Отсутствие поддержки ограничений при использовании операций 279
Создание обобщенных базовых классов 280
Создание обобщенных интерфейсов 282
Создание обобщенных делегатов 284
Несколько слов о вложенных делегатах 286
Задачи 286
Примеры реализации по шаблонам Мост+Фабрика 289
Пример 1 289
Пример 2 292
Пример 3. Контроллер в виде интерфейса, а не класса. 294
Различное поведение фабрик 298
Фабрики для создания плагинов 299
Фабрики для создания объектов по некоторому алгоритму 300
Фабрики для клонирования объектов 300
Некоторые замечания об использовании свойств и наследования 302
Замечания об использовании свойств 302
Замечания об использовании наследования. Проблема «хрупкого» базового класса. 304