Megosztás a következőn keresztül:


Mondja meg a hibakeresőnek, hogy mit jelenítsen meg a DebuggerDisplay attribútum használatával (C#, Visual Basic, F#, C++/CLI)

A DebuggerDisplayAttribute szabályozza, hogyan jelenik meg egy objektum, tulajdonság vagy mező a hibakereső változóablakaiban. Ez az attribútum alkalmazható típusokra (osztályokra, szerkezetekre, enumerálásokra, delegáltakra), de általában csak osztályokra és szerkezetekre alkalmazható. Ha egy alaptípusra alkalmazva van, az attribútum egy alosztályra is vonatkozik.

A DebuggerDisplay attribútum egyetlen argumentummal rendelkezik, amely karakterlánc, amit a típuspéldányok értékoszlopában kell megjeleníteni. Ez a sztring kapcsos zárójeleket ({ és }) tartalmazhat. A zárójelpáron belüli szöveg kiértékelése mezőként, tulajdonságként vagy metódusként történik.

Ha egy osztály felülírt ToString() metódussal rendelkezik, a hibakereső az alapértelmezett {<typeName>}helyett a felülírt metódust használja. Ebben az esetben nem kell használnia DebuggerDisplay. Ha mindkettőt használja, a DebuggerDisplay attribútum elsőbbséget élvez a felülírt ToString() metódusnál. A DebuggerDisplay attribútum elsőbbséget élvez az alosztály felülírt ToString() metódusával szemben.

Az, hogy a hibakereső kiértékeli-e ezt az implicit ToString() hívást, az Eszközök (vagy Hibakeresés) > csoportban található hibakeresési beállítástól függ.

Important

Ha a Változók ablakában az objektumok nyers szerkezetének megjelenítése lehetőséget választja, a rendszer figyelmen kívül hagyja az DebuggerDisplay attribútumot. Ez a beállítás az Eszközök>beállításai panelen, az Összes beállítás>hibakeresése>általános szakaszában található.

Important

Ha a Változók ablakában az objektumok nyers szerkezetének megjelenítése lehetőséget választja, a rendszer figyelmen kívül hagyja az DebuggerDisplay attribútumot. Ez a beállítás az Eszközök>beállításai párbeszédpanelen, a Hibakeresés>általános szakaszában található.

Note

Natív kód esetén ez az attribútum csak C++/CLI-kódban támogatott.

Az alábbi táblázat a DebuggerDisplay attribútum és a példakimenetek lehetséges használatát mutatja be.

Attribute Az Érték oszlopban megjelenő kimenet
[DebuggerDisplay("x = {x} y = {y}")]

x és ymezővel rendelkező típuson használatos.
x = 5 y = 18
[DebuggerDisplay("String value is {getString()}")]Paraméterszintaxis nyelvenként eltérő lehet. Ezért óvatosan használja. String value is [5, 6, 6]

DebuggerDisplay elnevezett paramétereket is elfogadhat.

Parameters Purpose
Name, Type Ezek a paraméterek hatással vannak a változóablakok Név és Típus oszlopára. (A konstruktor szintaxisával megegyező szintaxist használó sztringekre állíthatók be.) Ezeknek a paramétereknek a túlzott használata vagy helytelen használata zavaró kimenetet okozhat.
Target, TargetTypeName Megadja a céltípust, amikor az attribútumot a szerelvény szintjén használják.

A autoexp.cs fájl a DebuggerDisplay attribútumot használja a szerelvény szintjén. A autoexp.cs fájl határozza meg a Visual Studio által a .NET-objektumokhoz használt alapértelmezett bővítéseket. Megvizsgálhatja a autoexp.cs fájlt, például a DebuggerDisplay attribútum használatát, vagy módosíthatja és lefordíthatja a autoexp.cs fájlt az alapértelmezett bővítmények módosításához. A módosítás előtt győződjön meg arról, hogy biztonsági másolatot készít a autoexp.cs fájlról.

A autoexp.cs létrehozásához nyisson meg egy fejlesztői parancssort a VS2015-höz, és futtassa a következő parancsokat

cd <directory containing autoexp.cs>
csc /t:library autoexp.cs

A autoexp.dll módosításai a következő hibakeresési munkamenetben lesznek átvéve.

Kifejezések használata a DebuggerDisplayben

Bár a DebuggerDisplay attribútum kapcsos zárójelei között általános kifejezést is használhat, ez a gyakorlat nem ajánlott.

A DebuggerDisplay általános kifejezései kizárólag a céltípus aktuális példányához rendelkeznek implicit hozzáféréssel a this mutatóhoz. A kifejezés nem fér hozzá az aliasokhoz, a helyi beállításokhoz és a mutatókhoz. Ha a kifejezés tulajdonságokra hivatkozik, a tulajdonságok attribútumai nem lesznek feldolgozva. A C#-kód [DebuggerDisplay("Object {count - 2}")] például Object 6 jelenne meg, ha a mező count 8.

Ha kifejezéseket használ a DebuggerDisplayben, az a következő problémákhoz vezethet:

  • A kifejezések kiértékelése a hibakereső legdrágább művelete, és a kifejezés minden megjelenítéskor kiértékelésre kerül. Ez teljesítményproblémákat okozhat a kódon való áthaladás során. Egy gyűjtemény vagy lista értékeinek megjelenítésére használt összetett kifejezés például nagyon lassú lehet, ha az elemek száma nagy.

  • A kifejezéseket az aktuális veremkeret nyelvének kifejezésértékelője értékeli ki, nem pedig annak a nyelvnek a kiértékelője, amelyben a kifejezést írták. Ez kiszámíthatatlan eredményeket okozhat, ha a nyelvek eltérőek.

  • Egy kifejezés kiértékelése megváltoztathatja az alkalmazás állapotát. Egy tulajdonság értékét állító kifejezés például a végrehajtási kódban a tulajdonság értékét mutálja.

    A kifejezésértékelés lehetséges problémáinak csökkentésének egyik módja egy olyan privát tulajdonság létrehozása, amely végrehajtja a műveletet, és visszaad egy sztringet. A DebuggerDisplay attribútum ezután megjelenítheti a magántulajdonság értékét. Az alábbi példa ezt a mintát valósítja meg:

[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);
        }
    }
}

A ",nq" utótag azt jelzi a kifejezés kiértékelőjének, hogy távolítsa el az idézőjeleket a végső érték megjelenítésekor (nq = nincs idézőjel). A formázókkal kapcsolatos további információkért lásd a C# formátumjelölőit.

Example

Az alábbi példakód bemutatja, hogyan használható DebuggerDisplay, valamint DebuggerBrowsable és DebuggerTypeProxy. Amikor megnézi egy hibakereső változók ablakában, például a Watch ablakban, akkor a kibontás így néz ki:

Name Value Type
Key "three" objektum : {string}
Value 3 objektum : {int}
[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;
            }
        }
    }
}