Indiquez au débogueur ce qu’il doit afficher à l’aide de l’attribut DebuggerDisplay (C#, Visual Basic, F#, C++/CLI)
Article
Le DebuggerDisplayAttribute contrôle l’affichage d’un objet, d’une propriété ou d’un champ dans les fenêtres de variables du débogueur. Cet attribut peut être appliqué aux types (classes, structs, énumérations, délégués), mais est généralement appliqué uniquement aux classes et aux structs. S’il est appliqué à un type de base, l’attribut s’applique également à une sous-classe.
L’attribut DebuggerDisplay a un seul argument, qui est une chaîne à afficher dans la colonne valeur pour les instances du type. Cette chaîne peut contenir des accolades ({ et }). Le texte dans une paire d’accolades est évalué comme un champ, une propriété ou une méthode.
Si une classe a une méthode ToString() substituée, le débogueur utilise la méthode substituée au lieu du {<typeName>}par défaut. Par conséquent, si vous avez remplacé la méthode ToString(), le débogueur utilise la méthode substituée au lieu du {<typeName>}par défaut, et vous n’avez pas besoin d’utiliser DebuggerDisplay. Si vous utilisez les deux, l’attribut DebuggerDisplay est prioritaire sur la méthode ToString() substituée. L’attribut DebuggerDisplay est également prioritaire sur la méthode ToString() substituée dans une sous-classe.
L’évaluation par le débogueur de cet appel ToString() implicite dépend d’un paramètre utilisateur dans la boîte de dialogue Outils / Options / Débogage.
Important
Si la case à cocher Afficher la structure brute des objets dans les fenêtres variables est cochée dans la boîte de dialogue Outils / Options / Débogage, l’attribut DebuggerDisplay est ignoré.
Notes
Pour le code natif, cet attribut est pris en charge uniquement dans le code C++/CLI.
Le tableau suivant montre certaines utilisations possibles de l’attribut DebuggerDisplay et des exemples de sorties.
Attribut
Sortie apparaissant dans la colonne Valeur
[DebuggerDisplay("x = {x} y = {y}")]
Utilisé sur un type avec des champs x et y.
x = 5 y = 18
[DebuggerDisplay("String value is {getString()}")]syntaxe de paramètre peut varier d’un langage à l’autre. Par conséquent, utilisez-le avec soin.
String value is [5, 6, 6]
DebuggerDisplay peut également accepter des paramètres nommés.
Paramètres
Objectif
Name, Type
Ces paramètres affectent les colonnes Name et Type des fenêtres variables. (Ils peuvent être définis sur des chaînes à l’aide de la même syntaxe que le constructeur.) L’utilisation excessive de ces paramètres ou leur utilisation incorrecte peut entraîner une sortie déroutante.
Target, TargetTypeName
Spécifie le type cible lorsque l’attribut est utilisé au niveau de l’assembly.
Le fichier autoexp.cs utilise l’attribut DebuggerDisplay au niveau de l’assembly. Le fichier autoexp.cs détermine les expansions par défaut que Visual Studio utilise pour les objets .NET. Vous pouvez examiner le fichier autoexp.cs pour obtenir des exemples d’utilisation de l’attribut DebuggerDisplay, ou vous pouvez modifier et compiler le fichier autoexp.cs pour modifier les extensions par défaut. Veillez à sauvegarder le fichier autoexp.cs avant de le modifier.
Pour générer autoexp.cs, ouvrez une Invite de commandes développeur pour VS2015, puis exécutez les commandes suivantes
Invite de commandes Windows
cd <directory containing autoexp.cs>
csc /t:library autoexp.cs
Les modifications apportées à autoexp.dll seront prises en compte lors de la prochaine session de débogage.
Utilisation d’expressions dans DebuggerDisplay
Bien que vous puissiez utiliser une expression générale à l'intérieur de l'accolade dans un attribut DebuggerDisplay, cette méthode n'est pas recommandée.
Une expression générale dans DebuggerDisplay a un accès implicite au pointeur this pour l’instance actuelle du type cible uniquement. L'expression n'a accès ni aux alias, ni aux variables locales, ni aux pointeurs. Si l’expression fait référence à des propriétés, les attributs de ces propriétés ne sont pas traités. Par exemple, le code C# [DebuggerDisplay("Object {count - 2}")] affiche Object 6 si le champ count était 8.
L’utilisation d’expressions dans DebuggerDisplay peut entraîner les problèmes suivants :
L’évaluation des expressions est l’opération la plus coûteuse dans le débogueur et l’expression est évaluée chaque fois qu’elle est affichée. Cela peut entraîner des problèmes de performances lors de l’exécution pas à pas du code. Par exemple, une expression complexe utilisée pour afficher les valeurs d’une collection ou d’une liste peut être très lente lorsque le nombre d’éléments est volumineux.
Les expressions sont évaluées par l'évaluateur d'expression du langage du cadre de pile actuel et pas par l'évaluateur du langage dans lequel l'expression a été écrite. Cela peut entraîner des résultats imprévisibles lorsque les langues sont différentes.
L’évaluation d’une expression peut modifier l’état de l’application. Par exemple, une expression qui définit la valeur d’une propriété mute la valeur de propriété dans le code en cours d’exécution.
Une façon de réduire les problèmes possibles d’évaluation d’expression consiste à créer une propriété privée qui effectue l’opération et retourne une chaîne. L’attribut DebuggerDisplay peut ensuite afficher la valeur de cette propriété privée. L’exemple suivant implémente ce modèle :
Le suffixe « ,nq » indique à l’évaluateur d’expression de supprimer les guillemets lors de l’affichage de la valeur finale (nq = pas de guillemets).
Exemple
L’exemple de code suivant montre comment utiliser DebuggerDisplay, avec DebuggerBrowsable et DebuggerTypeProxy. Lorsqu'il s'affiche dans une fenêtre de variables du débogueur, comme la fenêtre Espion, il produit une expansion de ce genre :
Nom
Valeur
Type
Touche
« trois »
objet {string}
Valeur
3
objet {int}
C#
[DebuggerDisplay("{value}", Name = "{key}")]
internalclassKeyValuePairs
{
private IDictionary dictionary;
privateobject key;
privateobjectvalue;
publicKeyValuePairs(IDictionary dictionary, object key, objectvalue)
{
this.value = value;
this.key = key;
this.dictionary = dictionary;
}
publicobject Key
{
get { return key; }
set
{
object tempValue = dictionary[key];
dictionary.Remove(key);
key = value;
dictionary.Add(key, tempValue);
}
}
publicobject Value
{
get { returnthis.value; }
set
{
this.value = value;
dictionary[key] = this.value;
}
}
}
[DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(HashtableDebugView))]
classMyHashtable
{
public Hashtable hashtable;
publicMyHashtable()
{
hashtable = new Hashtable();
}
privatestring DebuggerDisplay { get { return"Count = " + hashtable.Count; } }
privateclassHashtableDebugView
{
private MyHashtable myhashtable;
publicHashtableDebugView(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;
}
}
}
}
Apprenez à déboguer efficacement votre application .NET en utilisant Visual Studio pour corriger rapidement vos bogues. Utilisez le débogueur interactif de Visual Studio pour analyser et corriger vos applications C#.