Чтение онлайн

ЖАНРЫ

Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:

• функцией, возвращающей значение;

• методом интерфейса;

• методом с модификатором override. Возможно его задание для virtual-метода. В этом случае атрибут наследуется методами потомков.

Атрибут Conditional, обычно с аргументом DEBUG, сопровождает модули, написанные для целей отладки. Но использование этого атрибута не ограничивается интересами отладки. Зачастую проект может использоваться в нескольких вариантах, например, в облегченном и более сложном. Методы, вызываемые в сложных ситуациях, например, ComplexMethod, имеющий атрибут условной компиляции, будут вызываться только в той конфигурации, где определена константа COMPLEX.

Приведу

пример работы с отладочными методами. Рассмотрим класс, в котором определены три метода, используемые при отладке:

public class DebugPrint

{

[Conditional("DEBUG")] static public void

PrintEntry(string name)

{

Console.WriteLine("Начал работать метод " + name);

}

[Conditional("DEBUG")] static public void

PrintExit(string name)

{

Console.WriteLine("Закончил работать метод " + name);

}

[Conditional("DEBUG")]

static public void PrintObject(object obj, string name)

{

Console.WriteLine("Объект {0}: {1}", name,

obj.ToString );

}

}

В классе Testing определено поле класса:

int state = 1;

и группа методов:

public void TestDebugPrint

{

DebugPrint.PrintEntry("Testing.TestDebugPrint");

PubMethod ;

DebugPrint.PrintObj ect(state, "Testing.state");

DebugPrint.PrintExit("Testing.TestDebugPrint");

}

void InMethod1

{

DebugPrint.PrintEntry("InMethod1");

// body

DebugPrint.PrintExit("InMethod1");

}

void InMethod2

{

DebugPrint.PrintEntry("InMethod2");

// body

DebugPrint.PrintExit("InMethod2");

}

public void PubMethod

{

DebugPrint.PrintEntry("PubMethod");

InMethod1 ;

state++;

InMethod2 ;

DebugPrint.PrintExit("PubMethod");

}

Этот пример демонстрирует трассировку хода вычислений, для чего в начало и конец каждого метода вставлены вызовы отладочных методов, снабжающие нас информацией о ходе вычислений. Такая трассировка иногда бывает крайне полезной на этапе отладки, но, естественно, она не должна присутствовать в финальной версии проекта. Взгляните на результаты, полученные при вызове метода TestDebugPrint в конфигурации Debug.

Рис. 23.1. Трассировка вычислений в процессе отладки

При переходе к конфигурации Release отладочная информация появляться не будет.

Классы Debug и Trace

Атрибут условной компиляции Conditional характеризует метод, но не отдельный оператор. Иногда хотелось бы иметь условный оператор печати, не создавая специального метода, как это было сделано в предыдущем примере. Такую возможность и многие другие полезные свойства предоставляют классы Debug и Trace.

Классы Debug и Trace — это классы-двойники. Оба они находятся в пространстве имен Diagnostics, имеют идентичный набор статических свойств и методов с идентичной семантикой. В чем же разница? Методы класса Debug имеют атрибут условной компиляции с константой DEBUG, действуют только в Debug-конфигурации проекта и игнорируются в Release-конфигурации. Методы класса Trace включают два атрибута Conditional с константами DEBUG и TRACE и действуют в обеих

конфигурациях.

Одна из основных групп методов этих классов — методы печати данных: Write, WriteIF, WriteLine, WriteLineIF. Методы перегружены, в простейшем случае позволяют выводить некоторое сообщение. Методы со словом If могут сделать печать условной, задавая условие печати в качестве первого аргумента метода, что иногда крайне полезно. Методы со словом Line дают возможность дополнять сообщение символом перехода на новую строку.

По умолчанию методы обоих классов направляют вывод в окно Output. Однако это не всегда целесообразно, особенно для Release-конфигурации. Замечательным свойством методов классов Debug и Trace является то, что они могут иметь много "слушателей", направляя вывод каждому из них. Свойство Listeners этих классов возвращает разделяемую обоими классами коллекцию слушателей — TraceListenerCollection. Как и всякая коллекция, она имеет ряд методов для добавления новых слушателей: Add, AddRange, Insert — и возможность удаления слушателей: Clear, Remove, RemoveAt и другие методы. Объекты этой коллекции в качестве предка имеют абстрактный класс TraceListener. Библиотека FCL включает три неабстрактных потомка этого класса:

DefauitTraceListener — слушатель этого класса, добавляется в коллекцию по умолчанию, направляет вывод, поступающий при вызове методов классов Debug и Trace, в окно Output;

EventLogTraceListener — посылает сообщения в журнал событий Windows;

TextWriterTraceListener — направляет сообщения объектам класса TextWriter или Stream; обычно один из объектов этого класса направляет вывод на консоль, другой — в файл.

Можно и самому создать потомка абстрактного класса, предложив, например, XML-слушателя, направляющего вывод в соответствующий XML-документ. Как видите, система управления выводом очень гибкая, позволяющая получать и сохранять информацию о ходе вычислений в самых разных местах.

Помимо свойства Listeners и методов печати, классы Debug и Trace имеют и другие важные методы и свойства:

Assert и Fail, проверяющие корректность хода вычислений — о них мы поговорим особо;

Flush — метод, отправляющий содержание буфера слушателю (в файл, на консоль и так далее). Следует помнить, что данные буферизуются, поэтому применение метода Flush зачастую необходимо, иначе метод может завершиться, а данные останутся в буфере;

AutoFiush — булево свойство, указывающее, следует ли после каждой операции записи данные из буфера направлять в соответствующий канал. По умолчанию свойство выключено, и происходит только буферизация данных;

Сlose — метод, опустошающий буфера и закрывающий всех слушателей, после чего им нельзя направлять сообщения.

У классов есть и другие свойства и методы, позволяющие, например, заниматься структурированием текста сообщений.

Рассмотрим пример работы, в котором отладочная информация направляется в разные каналы — окно вывода, консоль, файл:

public void Optima

{

double х, у=1;

х= у — 2*Math.Sin(у);

FileStream f = new FileStreamCDebuginfo.txt",

Поделиться с друзьями: