13

Tôi có một lớp học được kế thừa từ một số List<MagicBean>. Nó hoạt động tốt và như mong đợi ở tất cả các khía cạnh ngoại trừ một: khi tôi thêm thuộc tính [DebuggerDisplay]. Mặc dù nhìn vào Danh sách có số [DebuggerDisplay("Count = {Count}")], nếu tôi sao chép và dán nó lên bản thân, tôi mất khả năng nhìn trực tiếp vào tất cả các MagicBeans mà tôi không khoan vào các thành viên riêng trong khi gỡ lỗi.Làm cách nào để [DebuggerDisplay] tôn trọng các lớp kế thừa hoặc ít nhất là làm việc với các bộ sưu tập?

Làm cách nào để tận dụng tối đa cả hai thế giới? IE: Giá trị tùy chỉnh trong cột giá trị và Visual Studio không ẩn các hạt ma thuật của tôi khỏi tôi?

Trả lời

9

Bạn có thể nhận được hiệu ứng bạn cần bằng cách sử dụng thuộc tính DebuggerTypeProxy. Bạn cần phải tạo một lớp để thực hiện một debug "trực quan" danh sách kế thừa của bạn:

internal sealed class MagicBeanListDebugView 
{ 
    private List<MagicBean> list; 

    public MagicBeanListDebugView(List<MagicBean> list) 
    { 
     this.list = list; 
    } 

    [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] 
    public MagicBean[] Items{get {return list.ToArray();}} 
} 

Sau đó bạn có thể khai báo lớp này được sử dụng bởi các chương trình gỡ rối để hiển thị lớp học của bạn, cùng với các thuộc tính DebuggerDisplay:

[DebuggerDisplay("Count = {Count}")] 
[DebuggerTypeProxy(typeof(MagicBeanListDebugView))] 
public class MagicBeanList : List<MagicBean> 
{} 

Điều này sẽ cung cấp cho bạn thông báo "Count = 3" khi bạn di chuột qua một thể hiện danh sách được kế thừa trong Visual Studio và chế độ xem các mục trong danh sách khi bạn mở rộng nút gốc mà không cần phải khoan xuống các thuộc tính cơ sở.

Sử dụng ToString() để nhận được kết quả gỡ lỗi cụ thể không phải là cách tiếp cận tốt, trừ khi tất nhiên bạn đã ghi đè ToString() để sử dụng trong mã của bạn ở nơi khác, trong trường hợp này bạn có thể sử dụng nó.

+0

Tiện lợi, hữu ích, nhưng có vẻ khá sao chép và dán.Tôi không thể kiểm tra ngay bây giờ, nhưng có cách nào tôi có thể sử dụng danh sách mã đã sử dụng, hoặc ít nhất có thể viết một phiên bản chung một lần? Tôi ghét phải nhập điều này cho mọi lớp chứa tùy chỉnh. – MighMoS

+0

Sau khi đi qua một số đào, rõ ràng câu trả lời là không. – MighMoS

2

Sau khi xem bài viết "Using DebuggerDisplay Attribute" trên MSDN, chúng gợi ý rằng bạn có thể ghi đè hàm ToString() của lớp của bạn dưới dạng tùy chọn thay thế thay vì sử dụng thuộc tính DebuggerDisplay. Việc ghi đè phương thức ToString() cũng sẽ không ẩn đậu của bạn.

Nếu một đối tượng C# có ghi đè ToString(), trình gỡ lỗi sẽ gọi ghi đè và hiển thị kết quả của nó thay vì của chuẩn {}. Vì vậy, nếu bạn đã ghi đè ToString(), bạn thực hiện không phải sử dụng DebuggerDisplay. Nếu bạn sử dụng cả hai, thuộc tính DebuggerDisplay được ưu tiên hơn ghi đè ToString().

Bạn có thể ghi đè phương thức ToString() trên lớp học của mình hoặc bạn đang sử dụng nó cho các mục đích khác không?

Tôi không biết nếu bạn đã xem xét điều này hay chưa, nhưng tôi nghĩ tôi muốn đề nghị nó chỉ giúp ích. :-)

Để hoàn chỉnh, vì vậy bất kỳ ai khác có thể nhanh chóng giả lập; đây là ví dụ nhanh mà tôi đã thực hiện:

namespace StackOverflow 
{ 
    //broken BeanPouch class that uses the DebuggerDisplay attribute 
    [System.Diagnostics.DebuggerDisplay("Count = {Count}")] 
    class BrokenBeanPouch : List<MagicBean> 
    { } 

    //working BeanPouch class that overrides ToString 
    class WorkingBeanPouch : List<MagicBean> 
    { 
     public override string ToString() 
     { 
      return string.Format("Count = {0}", this.Count); 
     } 
    } 

    class Program 
    { 
     static WorkingBeanPouch myWorkingBeans = new WorkingBeanPouch() 
     { 
      new MagicBean() { Value = 4.99m }, new MagicBean() { Value = 5.99m }, new MagicBean() { Value = 3.99m } 
     }; 

     static BrokenBeanPouch myBrokenBeans = new BrokenBeanPouch() 
     { 
      new MagicBean() { Value = 4.99m }, new MagicBean() { Value = 5.99m }, new MagicBean() { Value = 3.99m } 
     }; 

     static void Main(string[] args) 
     { 
      //break here so we can watch the beans in the watch window 
      System.Diagnostics.Debugger.Break(); 
     } 
    } 

    class MagicBean 
    { 
     public decimal Value { get; set; } 
    }  
} 
0

Sử dụng thuộc tính DebuggerDisplay như vậy:

[DebuggerDisplay("ID:{ID},Customers:{Customers==null?(int?)null:Customers.Count}")]` 
class Project 
{ 
    int ID{get;set;} 
    IList<Customer> Customers{get;set;} 
} 

Một số biết thêm here.