Поделиться через


Использование атрибута DebuggerDisplay

Этот раздел применим к:

Выпуск

Visual Basic

C#

F#

C++

Web Developer

Express

Тема применяется Тема применяется Тема применяется Тема применяется Тема применяется

Pro, Premium и Ultimate

Тема применяется

Тема применяется

Тема применяется

Тема применяется

Тема применяется

Атрибут DebuggerDisplay (System.Diagnostics.DebuggerDisplayAttribute) управляет тем, как класс или поле отображается в окнах переменных отладчика. Этот атрибут может применяться для:

  • Классы

  • Структуры

  • Делегаты

  • Перечисленения

  • Поля

  • Свойства

  • сборкам.

Атрибут DebuggerDisplay имеет один аргумент, который является строкой, он отображается в столбце "значение" для экземпляров типа. Эта строка может содержать фигурные скобки ({ и }). Текст в паре фигурных скобок будет вычисляться как поле, свойство или метод.

Если в C# объект был переопределен ToString(), то отладчик вызовет переопределение и отобразит результат вместо стандартного {<typeName>}. Таким образом, если переопределен ToString(), то нет необходимости использовать DebuggerDisplay. Если используется и то и другое, то атрибут DebuggerDisplay будет иметь более высокий приоритет по отношению к переопределению ToString().

Выполнит ли отладчик этот неявный вызов ToString() , или нет - зависит от параметров пользователя в диалоговом окне Параметры (категория Отладка, страница Общие). Visual Basic не выполняет это неявное вычисление ToString().

Важно!

Если в диалоговом окне Сервис, Параметры установлен флажок Показывать базовую структуру объектов в окнах переменных, атрибут DebuggerDisplay игнорируется.

В следующей таблице показаны некоторые возможные способы использования атрибута DebuggerDisplay и пример выводов.

Атрибут

Вывод, появляющийся в столбце Значение)

[DebuggerDisplay("x = {x} y = {y}")]

Используется на типе с полями и x и y.

x = 5 y = 18

[DebuggerDisplay("String value is {getString()}")]

Синтаксис параметра может различаться в зависимости от языка. Поэтому используйте его с осторожностью.

String value is [5, 6, 6]

DebuggerDisplay может также принимать именованные параметры.

Параметры

Назначение

Name, Type

Эти параметры влияют на столбцы Имя и Тип окна переменных. (Они могут быть установлены в строки, используя тот же синтаксис, что и конструктор.)

Злоупотребление этими параметрами, или их неправильное использование, может привести к конфликтам на выходе.

Target, TargetTypeName

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

Примечание

Файл autoexp.cs использует атрибут DebuggerDisplay на уровне сборки.Файл autoexp.cs определяет расширения по умолчанию, которые Visual Studio использует для переменных C#.Можно проверить файл autoexp.cs на примерах способов использования атрибута DebuggerDisplay, или можно изменить и скомпилировать файл autoexp.cs чтобы изменить расширения по умолчанию.Не забудьте сделать резервную копию файла autoexp.cs прежде чем изменять его.Необходимо сослаться на Microsoft.VisualStudio.DebuggerVisualizers.dll в 10.0\Common7\IDE\PublicAssemblies \Program Files\Microsoft Visual Studio.Файл autoexp.cs можно найти в папке "Мои документы/Visual Studio 10.0/Visualizers.

Использование выражений в DebuggerDisplay

Хотя в атрибуте DebuggerDisplay можно использовать общее выражение между фигурными скобками, эта практика не рекомендуется.

Общее выражение в DebuggerDisplay имеет неявный доступ к указателю this для текущего экземпляра только целевого типа. Выражение не имеет доступа к псевдонимам, локальным переменным или указателям. Если выражение ссылается на свойства, то атрибуты для этих свойств не обрабатываются. Например, код C# [DebuggerDisplay("Object {count - 2}" отобразил бы Object 6, если бы поле count имело значение 8.

Использование выражений в DebuggerDisplay может привести к следующим проблемам:

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

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

  • Вычисление выражения может изменить состояние приложения. Например, выражение, которое задает значение свойства, изменяет значение свойства в выполняемом коде.

Одним из способов сократить возможные проблемы вычисления выражения является создание закрытого свойства, которое выполняет операцию и возвращает строку. Атрибут DebuggerDisplay может отобразить значение этого закрытого свойства. В следующем примере реализуется этот шаблон.

[DebuggerDisplay("{DebuggerDisplay,nq}")]
public sealed class MyClass {
    public int count { get; set; }
    public bool flag { get; set; }
    private string DebuggerDisplay {
        get{ return string.Format("("Object {0}", count - 2); }
    }
}

Пример

В следующем примере показано, как использовать DebuggerDisplay, вместе с DebuggerBrowseable и DebuggerTypeProxy. При просмотре переменных в окнах отладчика, например в окне Контрольные значения, он формирует расширение, которые выглядит следующим образом:

Имя

Значение

Type

Ключ

"три"

объект {строка}

Значение

3

объект {целое}

[DebuggerDisplay("{value}", Name = "{key}")]
internal class KeyValuePairs
{
    private IDictionary dictionary;
    private object key;
    private object value;
    public KeyValuePairs(IDictionary dictionary, object key, object value)
    {
        this.value = value;
        this.key = key;
        this.dictionary = dictionary;
    }

    public object Key
    {
        get { return key; }
        set
        {
            object tempValue = dictionary[key];
            dictionary.Remove(key);
            key = value;
            dictionary.Add(key, tempValue);
        }
    }

    public object Value
    {
        get { return this.value; }
        set
        {
            this.value = value;
            dictionary[key] = this.value;
        }
    }
}

[DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable
{
    public Hashtable hashtable;

    public MyHashtable()
    {
        hashtable = new Hashtable();  
    }

    private string DebuggerDisplay
    {
        get { return "Count = " + hashtable.Count); }
    }

    private class HashtableDebugView
    {
        private MyHashtable myhashtable;
        public HashtableDebugView(MyHashtable myhashtable)
        {
            this.myhashtable = myhashtable;
        }

        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        public KeyValuePairs[] Keys
        {
            get
            {
                KeyValuePairs[] keys = new KeyValuePairs[myhashtable.hashtable.Count];

                int i = 0;
                foreach (object key in myhashtable.hashtable.Keys)
                {
                    keys[i] = new KeyValuePairs(myhashtable.hashtable, key, myhashtable.hashtable[key]);
                    i++;
                }
                return keys;
            }
        }
    }
}

См. также

Ссылки

Использование атрибута DebuggerTypeProxy

Основные понятия

Отображение пользовательских типов данных

Повышение эффективности отладки с помощью атрибутов просмотра отладчика

Журнал изменений

Дата

Журнал

Причина

Май 2011

Добавлены предупреждения об использовании выражений в значениях атрибутов.

Улучшение информации.