Давайте рассмотрим несколько атрибутов, способных облегчить отладку .NET приложений.
[DebuggerDisplay]
Этот атрибут позволяет отобразить значения ключевых свойств экземпляра класса вместо типа в окнах Watch. Для этого необходимо добавить его в описание класса, указав имена этих свойств в фигурных скобках в качестве параметра. Например:
[DebuggerDisplay("{Date} => {Value}")]
internal class ChartPoint
{
public DateTime Date { get; set; }
public float Value { get; set; }
public string Hint { get; set; }
}
И тогда вместо стандартного
![[DebuggerDisplay] [DebuggerDisplay]](/image.axd?picture=csharp/debugger-attributes/DebuggerDisplay-off.png)
отладчик покажет следующее:
![[DebuggerDisplay] [DebuggerDisplay]](/image.axd?picture=csharp/debugger-attributes/DebuggerDisplay-on.png)
Кроме того, такое решение удобно для перечислений. Например:
![[DebuggerDisplay] для массива [DebuggerDisplay] для массива](/image.axd?picture=csharp/debugger-attributes/DebuggerDisplay-array.png)
[DebuggerBrowsable]
Это атрибут, определяющий что будет отображено в окне отладчика. Позволяет указать одно из трех состояний, определенных в перечислении DebuggerBrowsableState:
- Never – не показывать элемент (полезен при создании библиотечных классов и компонент);
- Collapsed – показывать свернутым (поведение по умолчанию);
- RootHidden – не показывать сам элемент, но показывать содержащуюся в нем коллекцию.
Посмотрим пример:
internal class ChartData
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _chartId;
public string Title { get; set; }
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public ChartPoint[] Points { get; set; }
}
В данном случае, поле _chartId не будет отображено в окне отладчика, а точки Points будут показаны сразу на уровне экземпляра. Обратите внимание, что [DebuggerDisplay], указанный для класса ChartPoint, по-прежнему сразу отображает значения указанных свойств:
![[DebuggerBrowsable] [DebuggerBrowsable]](/image.axd?picture=csharp/debugger-attributes/DebuggerBrowsable.png)
[DebuggerStepThrough]
DebuggerStepThroughAttribute позволяет указать метод, в который отладчик не должен заходить в пошаговом режиме. Однако установленные внутри точки останова сработают (опция отладчика "Just My Code" должна быть выключена).
[DebuggerHidden]
Этот атрибут полностью скрывает элемент от отладчика. Использование его со свойством аналогично [DebuggerBrowsable(DebuggerBrowsableState.Never)]. При добавлении его к методу, отладчик в пошаговом режиме не только проигнорирует сам метод, но и установленные внутри точки останова.
[DebuggerTypeProxy]
DebuggerTypeProxyAttribute позволяет задать объект, который будет использоваться для отображения данных экземпляра в отладке. Это позволяет кардинально изменить вид объекта в отладчике.
Прокси это обычный класс, но с единственным условием – параметром его конструктора должен быть экземпляр исходного типа. Например, с помощью данной техники отобразим для ChartData максимальную дату и среднее значение:
internal class ChartDataDebugView
{
private readonly ChartData _chartData;
public ChartDataDebugView(ChartData chartData)
{
this._chartData = chartData;
}
public DateTime MaxDate
{
get { return this._chartData.Points.Max(p => p.Date); }
}
public float AverageValue
{
get { return this._chartData.Points.Average(p => p.Value); }
}
}
[DebuggerTypeProxy(typeof(ChartDataDebugView))]
[DebuggerDisplay("{Title}")]
internal class ChartData
{
private int _chartId;
public string Title { get; set; }
public ChartPoint[] Points { get; set; }
}
![[DebuggerTypeProxy] [DebuggerTypeProxy]](/image.axd?picture=csharp/debugger-attributes/DebuggerTypeProxy-on.png)
Ссылка Raw View позволяет посмотреть оригинальный экземпляр. Также обратите внимание, что [DebuggerDisplay] в данном случае работает со свойствами исходного типа.
[DebuggerVisualizer]
И в завершении, стоит упомянуть еще один атрибут – DebuggerVisualizerAttribute, который позволяет указать собственный класс для отображения текущих значений. В данном случае весь вывод информации, включая диалоговое окно, полностью ложиться на разработчика.
Для упрощения этой задачи можно использовать абстрактный базовый класс DialogDebuggerVisualizer, реализующий окно вывода. В этом случае, необходимо переопределить его метод Show() для отображения информации. Простейшую реализацию такого подхода можно посмотреть в MSDN.