ael
ael

Reputation: 534

debuggerdisplay doesn't display field value as expected

public class A
{
    [DebuggerDisplay("{DDBpp1()}")]
    public byte[] Bpp = new byte[2];

    public string DDBpp1()
    {
        return "DDBpp";
    }

    public string DDBpp2()
    {
        short result;

        if (BitConverter.IsLittleEndian)
        {
            var bppCopy = new byte[2];
            Bpp.CopyTo(bppCopy, 0);
            Array.Reverse(bppCopy);
            result = BitConverter.ToInt16(bppCopy, 0);
        }
        else
        {
            result = BitConverter.ToInt16(Bpp, 0);
        }

        return result.ToString();
    }
}

It doesn't matter which method I use in the DebuggerDisplay attribute (DDBpp1 or DDBpp2). Value column under debugger is always filled by {byte[2]}. I expected string "DDBpp" for DDBpp1() method or short value for DDBpp2() method. The issue appears under VS15/17 Community.

Is it possible to change displaying field value under debugger?

Upvotes: 3

Views: 1016

Answers (2)

Olaf
Olaf

Reputation: 101

Have you checked:

"If the Show raw structure of objects in variables windows check box is selected in the Tools Options dialog box, then the DebuggerDisplay attribute is ignored"

Upvotes: 3

Patrick Artner
Patrick Artner

Reputation: 51663

If you put [DebuggerDisplay("{DDBpp2()}")] on the class itself, it will display the bytes[] shifted int16 content in the debugger - for the class:

DebuggerDisplayAttribute on class

It makes no difference if you implement Bpp as member or property, and giving it more attributes does not help either.

    [DebuggerDisplay("{DDBpp2()}", Name = "{DDBpp2()}", TargetTypeName = "{DDBpp2()}", Type = "{DDBpp2()}"]
    public byte[] Bpp { get; set; } = new byte[2];

Maybe putting it on the class helps you out:

[DebuggerDisplay("{CDBpp2()}")]
[DebuggerDisplay("{DDBpp2()}")]
public class A
{
    [DebuggerDisplay("{DDBpp2()}", Name = "{DDBpp2()}", TargetTypeName = "{DDBpp2()}", Type = "{DDBpp2()}")]
    public byte[] Bpp { get; set; } = new byte[2] { 255, 255 };

    public byte[] Cpp { get; set; } = new byte[2] { 11, 28 };

    public string CDBpp2() => ToDebugStr(Cpp);

    public string DDBpp2() => ToDebugStr(Bpp);

    string ToDebugStr(byte[] b)
    {
        short result;
        if (BitConverter.IsLittleEndian)
        {
            var bppCopy = new byte[2];
            b.CopyTo(bppCopy, 0);
            Array.Reverse(bppCopy);
            result = BitConverter.ToInt16(bppCopy, 0);
        }
        else
        {
            result = BitConverter.ToInt16(b, 0);
        }
        return result.ToString();
    }
}

If you have a close look at the given examples on the msdn documentation, you'll see that the attribute is ever only applied on class level - I am stumped though, why they did not limit the attribute to classes then.

I took a look at the source of debuggerDisplayAttribute.cs - it is appliccable to more then classes and you can even use is multiple times.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Assembly, AllowMultiple = true)]

My guess would be that VS does not implement all the possible outcomes on members/properties/etc. for the IDE and thats why it does not work. If you supply the attribute multiple times, only the first is used in debugger view: see my example and debugg it.

Upvotes: 3

Related Questions