DebuggerDisplay Özniteliğini (C#, Visual Basic, F#, C++/CLI) kullanarak hata ayıklayıcıya ne göstereceğini söyleyin

bir DebuggerDisplayAttribute nesnenin, özelliğin veya alanın hata ayıklayıcı değişken pencerelerinde nasıl görüntüleneceğini denetler. Bu öznitelik türlere (sınıflar, yapılar, sabit listeleri, temsilciler) uygulanabilir. Temel türe uygulanırsa, özniteliği bir alt sınıfa da uygulanır.

özniteliği, DebuggerDisplay tür örnekleri için değer sütununda görüntülenecek bir dize olan tek bir bağımsız değişkene sahiptir. Bu dize ayraçlar ({ ve }) içerebilir. Bir küme ayracı çifti içindeki metin alan, özellik veya yöntem olarak değerlendirilir.

Bir sınıfın geçersiz kılınmış ToString() bir yöntemi varsa, hata ayıklayıcı varsayılan {<typeName>}yerine geçersiz kılınan yöntemini kullanır. Bu nedenle, yöntemini geçersiz kıldıysanız ToString() , hata ayıklayıcı varsayılan {<typeName>}yerine geçersiz kılınan yöntemini kullanır ve kullanmanız DebuggerDisplaygerekmez. Her ikisini de kullanırsanız, DebuggerDisplay özniteliği geçersiz kılınan ToString() yöntemden önceliklidir. DebuggerDisplay özniteliği de bir alt sınıfta geçersiz kılınan ToString() yöntemden önceliklidir.

Hata ayıklayıcının bu örtük ToString() çağrıyı değerlendirip değerlendirmediği, Araçlar / Seçenekler / Hata Ayıklama iletişim kutusundaki bir kullanıcı ayarına bağlıdır.

Önemli

Araçlar / Seçenekler / Hata Ayıklama iletişim kutusunda Değişkenlerin ham yapısını göster onay kutusu seçiliyse, DebuggerDisplay öznitelik yoksayılır.

Dekont

Yerel kod için bu öznitelik yalnızca C++/CLI kodunda desteklenir.

Aşağıdaki tabloda özniteliğin DebuggerDisplay bazı olası kullanımları ve örnek çıkışlar gösterilmektedir.

Öznitelik Değer sütununda görünen çıktı
[DebuggerDisplay("x = {x} y = {y}")]

ve yalanları x olan bir tür üzerinde kullanılır.
x = 5 y = 18
[DebuggerDisplay("String value is {getString()}")]Parametre söz dizimi diller arasında farklılık gösterebilir. Bu nedenle, dikkatli kullanın. String value is [5, 6, 6]

DebuggerDisplay adlandırılmış parametreleri de kabul edebilir.

Parametreler Amaç
Name, Type Bu parametreler, değişken pencerelerinin Ad ve Tür sütunlarını etkiler. (Oluşturucuyla aynı söz dizimi kullanılarak dizelere ayarlanabilirler.) Bu parametrelerin aşırı kullanılması veya yanlış kullanılması kafa karıştırıcı bir çıkışa neden olabilir.
Target, TargetTypeName Öznitelik derleme düzeyinde kullanıldığında hedef türü belirtir.

autoexp.cs dosyası, derleme düzeyinde DebuggerDisplay özniteliğini kullanır. autoexp.cs dosyası, Visual Studio'da .NET nesneleri için kullanılan varsayılan genişletmeleri belirler. DebuggerDisplay özniteliğini kullanma örnekleri için autoexp.cs dosyasını inceleyebilir veya varsayılan genişletmeleri değiştirmek için autoexp.cs dosyasını değiştirebilir ve derleyebilirsiniz. Autoexp.cs dosyasını değiştirmeden önce yedeklediğinizden emin olun.

autoexp.cs oluşturmak için VS2015 için bir Geliştirici Komut İstemi açın ve aşağıdaki komutları çalıştırın

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

autoexp.dll dosyasındaki değişiklikler bir sonraki hata ayıklama oturumunda alınacaktır.

DebuggerDisplay'de İfadeleri Kullanma

DebuggerDisplay özniteliğindeki küme ayraçları arasında genel bir ifade kullanabilirsiniz ancak bu uygulama önerilmez.

DebuggerDisplay içindeki genel bir ifade, yalnızca hedef türün this geçerli örneği için işaretçiye örtük erişime sahiptir. İfadenin diğer adlara, yerel ayarlara veya işaretçilere erişimi yoktur. İfade özelliklere başvuruyorsa, bu özelliklerdeki öznitelikler işlenmez. Örneğin, alan count 8 ise C# kodu [DebuggerDisplay("Object {count - 2}")] görüntülenirObject 6.

DebuggerDisplay'de ifadelerin kullanılması aşağıdaki sorunlara yol açabilir:

  • İfadelerin değerlendirilmesi hata ayıklayıcıdaki en pahalı işlemdir ve ifade her görüntülendiğinde değerlendirilir. Bu, kodda adım adım performans sorunlarına neden olabilir. Örneğin, bir koleksiyondaki veya listedeki değerleri görüntülemek için kullanılan karmaşık bir ifade, öğe sayısı büyük olduğunda çok yavaş olabilir.

  • İfadeler, ifadenin yazıldığı dilin değerlendiricisi tarafından değil, geçerli yığın çerçevesinin dilinin ifade değerlendiricisi tarafından değerlendirilir. Bu, diller farklı olduğunda öngörülemeyen sonuçlara neden olabilir.

  • bir ifadenin değerlendirilmesi uygulamanın durumunu değiştirebilir. Örneğin, bir özelliğin değerini ayarlayan bir ifade, yürütülen koddaki özellik değerini sessize alır.

    İfade değerlendirmesinin olası sorunlarını azaltmanın bir yolu, işlemi gerçekleştiren ve dize döndüren bir özel özellik oluşturmaktır. DebuggerDisplay özniteliği daha sonra bu özel özelliğin değerini görüntüleyebilir. Aşağıdaki örnek bu düzeni uygular:

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

",nq" soneki, ifade değerlendiricisine son değeri görüntülerken tırnak işaretlerini kaldırmasını söyler (nq = tırnak yok).

Örnek

Aşağıdaki kod örneğinde ve DebuggerTypeProxyile DebuggerBrowsable birlikte öğesinin nasıl kullanılacağı DebuggerDisplaygösterilmektedir. İzleme penceresi gibi bir hata ayıklayıcısı değişkenleri penceresinde görüntülendiğinde şuna benzer bir genişletme oluşturur:

Adı Değer Türü
Tuş "üç" object {string}
Değer 3 {int} nesnesi
[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;
            }
        }
    }
}