Как заставить [DebuggerDisplay] уважать унаследованные классы или, по крайней мере, работать с коллекциями?
У меня есть класс, который наследуется от List<MagicBean>
. Он работает хорошо и, как ожидается, во всех отношениях, кроме одного: когда я добавляю атрибут [DebuggerDisplay]
. Несмотря на то, что просмотр списка имеет [DebuggerDisplay("Count = {Count}")]
, если я так же копирую и вставляю его в свою, я теряю возможность смотреть прямо на все MagicBeans, которые у меня есть, без сверления в base- > private членов при отладке.
Как я могу получить лучшее из обоих миров? IE: пользовательское значение в столбце значений, а Visual Studio не скрывает от меня мою магию beans?
Ответы
Ответ 1
Вы можете получить необходимый эффект, используя атрибут DebuggerTypeProxy. Вам нужно создать класс для отладки "визуализации" вашего унаследованного списка:
internal sealed class MagicBeanListDebugView
{
private List<MagicBean> list;
public MagicBeanListDebugView(List<MagicBean> list)
{
this.list = list;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public MagicBean[] Items{get {return list.ToArray();}}
}
Затем вы можете объявить этот класс для использования отладчиком для отображения вашего класса вместе с атрибутом DebuggerDisplay
:
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(MagicBeanListDebugView))]
public class MagicBeanList : List<MagicBean>
{}
Это даст вам сообщение "Count = 3" при наведении курсора на экземпляр вашего унаследованного списка в Visual Studio и представление элементов в списке при расширении корневого node без необходимости сверления вниз в базовые свойства.
Использование ToString()
для получения результата отладки не является хорошим подходом, если, конечно, вы уже не переопределяете ToString()
для использования в вашем коде в другом месте, и в этом случае вы можете его использовать.
Ответ 2
Посмотрев на статью Using DebuggerDisplay Attribute в MSDN, они предлагают переопределить функцию ToString() вашего класса как альтернативный вариант, а не использовать атрибут DebuggerDisplay. Переопределение метода ToString() не скроет ваш beans.
Если объект С# переопределен ToString(), отладчик вызовет переопределить и показать результат стандартного {}. Таким образом, если вы переопределили ToString(), вы делаете не нужно использовать DebuggerDisplay. Если вы используете оба варианта, DebuggerDisplay атрибут имеет приоритет над ToString() переопределяет.
Можно ли переопределить метод ToString() в вашем классе или использовать его для других целей?
Я не знаю, считали ли вы это или нет, но я подумал, что предлагаю ему просто помочь.: -)
Для полноты, чтобы кто-нибудь еще мог быстро издеваться над этим; вот быстрый пример, который я сделал:
namespace StackOverflow
{
//broken BeanPouch class that uses the DebuggerDisplay attribute
[System.Diagnostics.DebuggerDisplay("Count = {Count}")]
class BrokenBeanPouch : List<MagicBean>
{ }
//working BeanPouch class that overrides ToString
class WorkingBeanPouch : List<MagicBean>
{
public override string ToString()
{
return string.Format("Count = {0}", this.Count);
}
}
class Program
{
static WorkingBeanPouch myWorkingBeans = new WorkingBeanPouch()
{
new MagicBean() { Value = 4.99m }, new MagicBean() { Value = 5.99m }, new MagicBean() { Value = 3.99m }
};
static BrokenBeanPouch myBrokenBeans = new BrokenBeanPouch()
{
new MagicBean() { Value = 4.99m }, new MagicBean() { Value = 5.99m }, new MagicBean() { Value = 3.99m }
};
static void Main(string[] args)
{
//break here so we can watch the beans in the watch window
System.Diagnostics.Debugger.Break();
}
}
class MagicBean
{
public decimal Value { get; set; }
}
}
Ответ 3
Используйте атрибут DebuggerDisplay следующим образом:
[DebuggerDisplay("ID:{ID},Customers:{Customers==null?(int?)null:Customers.Count}")]`
class Project
{
int ID{get;set;}
IList<Customer> Customers{get;set;}
}
Дополнительная информация здесь.