2013-12-16 13 views
8

Đây là nguồn thực tế cho .NET của System.Exception.ToString:Tại sao System.Exception.ToString không gọi hàm ToString ảo cho các ngoại lệ bên trong?

public override string ToString() 
{ 
    return this.ToString(true, true); 
} 

private string ToString(bool needFileLineInfo, bool needMessage) 
{ 
    string str1 = needMessage ? this.Message : (string) null; 
    string str2 = str1 == null || str1.Length <= 0 ? this.GetClassName() : this.GetClassName() + ": " + str1; 
    if (this._innerException != null) 
    str2 = str2 + " ---> " + this._innerException.ToString(needFileLineInfo, needMessage) + Environment.NewLine + " " + Environment.GetRuntimeResourceString("Exception_EndOfInnerExceptionStack"); 
    string stackTrace = this.GetStackTrace(needFileLineInfo); 
    if (stackTrace != null) 
    str2 = str2 + Environment.NewLine + stackTrace; 
    return str2; 
} 

Ngoài những xấu xa tuyệt đối, người ta có thể nhận thấy rằng cho tất cả các trường hợp ngoại lệ bên trong tư nhân, ToString phi ảo sẽ được gọi. Nói cách khác, nếu bạn quá tải ToString trong trường hợp ngoại lệ , nó sẽ không được gọi nếu ngoại lệ của bạn xảy ra được lồng nhau. Ồ, chờ đã, hóa ra các ngoại lệ tích hợp có cùng vấn đề, ví dụ: System.IO.FileNotFoundException in ra đường dẫn của tập tin - nó không phải là một phần của tin nhắn:

public override string ToString() 
{ 
    string str = this.GetType().FullName + ": " + this.Message; 
    if (this._fileName != null && this._fileName.Length != 0) 
    str = str + Environment.NewLine + Environment.GetResourceString("IO.FileName_Name", new object[1] 
    { 
     (object) this._fileName 
    }); 
    ... 
} 

Nhưng nếu bạn quấn một thể hiện ... thông tin này sẽ bị mất, trừ khi bạn đi qua cây ngoại lệ bản thân và phát hiện trường hợp ngoại lệ hãy gọi hoặc tự gọi số ToString và thực hiện một số phân tích cú pháp.

Đó là một sự bất tiện khó chịu, làm cho các hộp thoại ghi nhật ký/ghi lỗi hoặc mất thông tin hoặc bị lỗi. Điều thú vị là Mono gets it right.

Có bất kỳ sự khôn ngoan ẩn nào trong phiên bản .NET không?

EDIT: đây không phải là câu hỏi dựa trên ý kiến. Trong khi tôi thấy sự lựa chọn thiết kế này gây phiền nhiễu, tôi muốn biết những lợi ích của phương pháp này. Biết chúng có thể có lợi khi desiging giải pháp mới.

Trả lời

1

Theo kinh nghiệm của tôi, không bao gồm các chi tiết ngoại lệ bên trong trong lời gọi đến ToString là quyết định đúng đắn của các nhà thiết kế khung.

Thông thường, kết quả của ToString được trình bày cho người dùng cuối trong trường hợp ứng dụng thực thi không thể cung cấp cho người dùng thông tin chính xác hơn về bản chất của sự cố và giải pháp có thể.

Trong trường hợp này, việc lồng các chi tiết ngoại lệ nội bộ có thể không chỉ gây nhầm lẫn cho người dùng cuối, nó cũng có thể gây ra rủi ro bảo mật tiềm ẩn. Ví dụ về vấn đề tên tệp ở trên là tốt nhất: tôi không muốn để lộ thông tin thư mục của một tệp trên máy chủ web của tôi cho người dùng bên ngoài trong trường hợp tệp không thể tìm thấy (theo lý thuyết, ngoại lệ sẽ luôn luôn xảy ra được xử lý một cách chính xác để ngăn chặn sự tiếp xúc này, nhưng không có ứng dụng nào là hoàn hảo).

Trường hợp chi tiết ngoại lệ bên trong trở nên hữu ích là ghi nhật ký lỗi ứng dụng ở đâu đó (nhật ký sự kiện, tệp, cơ sở dữ liệu, v.v.). Trong trường hợp này, bạn rất có thể sẽ muốn nhiều hơn chỉ các chi tiết ToString, vì vậy hàm ý là vì bạn phải có mã đăng nhập cho các tình huống này, mã đăng nhập này là những gì chịu trách nhiệm trích xuất thông tin thích hợp.

Tôi tin rằng Microsoft đã sớm nhận ra điều này vì một trong những Khối ứng dụng đầu tiên được thêm vào Thư viện doanh nghiệp của họ là Exception Handling block, cung cấp thông tin chi tiết về ngoại lệ và ghi lại tất cả các chi tiết ngoại lệ. chính họ.

+0

Tôi nhận được quan điểm của bạn, nhưng lưu ý rằng việc trình bày ngăn xếp ngoại lệ và/hoặc ngăn xếp cuộc gọi cho người dùng có thể là một lỗi bảo mật. Chưa kể rằng 'ToString' mặc định cũng in thuộc tính' Message', có thể chứa dữ liệu nhạy cảm. Vì vậy, nếu đây là một quyết định thiết kế của Microsoft, nó đã trở thành một trung gian không phục vụ an ninh, cũng không phải là thông tin; cho các chương trình "bán lẻ", bạn không nên hiển thị kết quả của 'ToString' ở tất cả, cho công nghệ trong nhà bạn cần thêm thông tin (nó là ra khỏi đó!). – gwiazdorrr

2

Exception.ToString() không phải là thứ sẽ được hiển thị cho người dùng. Nó nội dung nào đó sẽ được trình bày cho nhà phát triển, có thể trong tệp nhật ký.

Việc triển khai mặc định ToString() thường là "điều đúng".Lưu ý cách nó xử lý các ngoại lệ lồng nhau và nhiều ngoại lệ (như AggregateException hoặc SqlException) và thậm chí là ngoại lệ trên một ranh giới truy cập từ xa. Hãy thử nhận được một lỗi trong quá trình deserialization của XML với serializer XML, và bạn sẽ thực sự đánh giá cao bao nhiêu thông tin nó mang lại cho bạn - thường là đủ để chỉ trực tiếp đến nguyên nhân của ngoại lệ.

Nếu có điều gì đó cụ thể mà bạn muốn xem được hiển thị, thì bạn nên tham gia với Microsoft về vấn đề này. Đặc biệt, bạn không có khả năng khiến họ đơn giản gọi ToString bị ghi đè của bạn. Rõ ràng, không muốn. Tuy nhiên, nếu có thứ gì đó mà ToString của bạn muốn hiển thị là của họ thì không, sau đó nói chuyện với họ và xem liệu có cách nào khác để đi hay không, hoặc có điều gì họ có thể làm trong bản phát hành sau này.

Các vấn đề liên quan