Câu hỏi Bắt nhiều ngoại lệ cùng một lúc?


Nó không được khuyến khích để chỉ bắt System.Exception. Thay vào đó, chỉ những ngoại lệ "đã biết" mới bị bắt.

Bây giờ, điều này đôi khi dẫn đến mã lặp đi lặp lại không cần thiết, ví dụ:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
    WebId = Guid.Empty;
}
catch (OverflowException)
{
    WebId = Guid.Empty;
}

Tôi tự hỏi: Có cách nào để bắt cả hai trường hợp ngoại lệ và chỉ gọi WebId = Guid.Empty gọi một lần?

Ví dụ được cho là khá đơn giản, vì nó chỉ là một GUID. Nhưng hãy tưởng tượng mã nơi bạn sửa đổi một đối tượng nhiều lần và nếu một trong các thao tác thất bại theo cách mong đợi, bạn muốn "đặt lại" object. Tuy nhiên, nếu có một ngoại lệ bất ngờ, tôi vẫn muốn ném nó cao hơn.


1712
2017-09-25 20:56


gốc


Nếu bạn đang sử dụng .net 4 và ở trên tôi thích sử dụng aggregateexception msdn.microsoft.com/en-us/library/system.aggregateexception.aspx - Bepenfriends
Bepenfriends- Kể từ khi System.Guid không ném AggregateException, nó sẽ là tuyệt vời nếu bạn (hoặc ai đó) có thể gửi một câu trả lời cho thấy làm thế nào bạn sẽ quấn nó vào một AggregateException vv .. - weir
Đang sử dụng AggregateException: Ném một AggregateException trong mã của riêng tôi - DavidRR
"Nó không được khuyến khích để chỉ bắt System.Exception." -và nếu phương pháp có thể ném 32 loại ngoại lệ, thì cái gì sẽ xảy ra? viết bắt cho mỗi người trong số họ một cách riêng biệt? - giorgi.m
Giữ nó theo cách bạn có nó. Di chuyển mã tới trình xử lý lỗi nếu bạn muốn chỉ có một dòng cho mỗi câu lệnh khai thác. - rolls


Các câu trả lời:


Bắt lấy System.Exception và bật các loại

catch (Exception ex)            
{                
    if (ex is FormatException || ex is OverflowException)
    {
        WebId = Guid.Empty;
        return;
    }

    throw;
}

1792
2017-09-25 21:01



Thật không may, FxCop (tức là - Visual Studio Mã phân tích) không thích nó khi bạn bắt ngoại lệ. - Andrew Garrison
Tôi đồng ý không bắt ngoại lệ, nhưng, trong trường hợp này, bắt là bộ lọc. Bạn có thể có một lớp cao hơn sẽ xử lý các loại ngoại lệ khác. Tôi sẽ nói điều này là chính xác, mặc dù nó bao gồm một catch (ngoại lệ x). Nó không sửa đổi luồng chương trình, nó chỉ xử lý các ngoại lệ nhất định sau đó cho phép phần còn lại của ứng dụng đối phó với bất kỳ loại ngoại lệ nào khác. - lkg
Phiên bản mới nhất của FxCop không ném ngoại lệ khi mã trên được sử dụng. - Peter
Không chắc chắn những gì đã sai với mã của OP ở nơi đầu tiên. Câu trả lời được chấp nhận # 1 gần gấp đôi số dòng và ít dễ đọc hơn. - João Bragança
@ JoãoBragança: Trong khi câu trả lời trong ví dụ này sử dụng nhiều dòng hơn, hãy thử tưởng tượng nếu bạn đang xử lý tệp IO chẳng hạn, và tất cả những gì bạn muốn làm là bắt những ngoại lệ đó và thực hiện một số thông điệp tường trình, nhưng chỉ những người bạn mong đợi đến từ tập tin các phương thức IO. Sau đó, bạn thường phải đối phó với một số lượng lớn hơn (khoảng 5 hoặc nhiều hơn) các loại ngoại lệ khác nhau. Trong tình huống đó, cách tiếp cận này có thể giúp bạn tiết kiệm một số dòng. - Xilconic


CHỈNH SỬA: Tôi đồng ý với những người đang nói rằng, như của C # 6.0, bộ lọc ngoại lệ bây giờ là một cách hoàn toàn tốt đẹp để đi: catch (Exception ex) when (ex is ... || ex is ... )

Ngoại trừ việc tôi vẫn rất ghét bố cục dài dòng và cá nhân sẽ đặt mã như sau. Tôi nghĩ rằng đây là chức năng vì nó là thẩm mỹ, vì tôi tin rằng nó cải thiện sự hiểu biết. Một số có thể không đồng ý:

catch (Exception ex) when (
    ex is ...
    || ex is ...
    || ex is ...
)

NGUYÊN:

Tôi biết tôi hơi muộn đến bữa tiệc ở đây, nhưng khói thánh ...

Cắt thẳng theo đuổi, kiểu này trùng lặp với câu trả lời trước đó, nhưng nếu bạn thực sự muốn thực hiện một hành động chung cho một vài loại ngoại lệ và giữ toàn bộ điều gọn gàng và gọn gàng trong phạm vi của một phương pháp, tại sao không chỉ sử dụng lambda / đóng cửa / inline chức năng để làm một cái gì đó như sau? Ý tôi là, rất có thể bạn sẽ nhận ra rằng bạn chỉ muốn đóng cửa một phương pháp riêng biệt mà bạn có thể sử dụng ở khắp mọi nơi. Nhưng sau đó nó sẽ được siêu dễ dàng để làm điều đó mà không thực sự thay đổi phần còn lại của mã cấu trúc. Đúng?

private void TestMethod ()
{
    Action<Exception> errorHandler = ( ex ) => {
        // write to a log, whatever...
    };

    try
    {
        // try some stuff
    }
    catch ( FormatException  ex ) { errorHandler ( ex ); }
    catch ( OverflowException ex ) { errorHandler ( ex ); }
    catch ( ArgumentNullException ex ) { errorHandler ( ex ); }
}

Tôi không thể không tự hỏi (cảnh báo: một chút mỉa mai / mỉa mai phía trước) tại sao trên trái đất đi đến tất cả các nỗ lực này về cơ bản chỉ cần thay thế sau đây:

try
{
    // try some stuff
}
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}

... với một số biến thể điên rồ của mùi mã tiếp theo này, tôi có nghĩa là ví dụ, chỉ giả vờ rằng bạn đang tiết kiệm một vài tổ hợp phím.

// sorta sucks, let's be honest...
try
{
    // try some stuff
}
catch( Exception ex )
{
    if (ex is FormatException ||
        ex is OverflowException ||
        ex is ArgumentNullException)
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

Bởi vì nó chắc chắn không tự động đọc được.

Cấp, tôi để lại ba trường hợp giống nhau của /* write to a log, whatever... */ return; trong ví dụ đầu tiên.

Nhưng đó là điểm của tôi. Y'all đã nghe nói về các chức năng / phương pháp, phải không? Nghiêm túc. Viết chung ErrorHandler chức năng và, giống như, gọi nó từ mỗi khối catch.

Nếu bạn hỏi tôi, ví dụ thứ hai (với if và is từ khoá) vừa dễ đọc hơn vừa đáng kể, đồng thời dễ bị lỗi nhiều hơn trong giai đoạn bảo trì của dự án của bạn.

Giai đoạn bảo trì, cho bất kỳ ai có thể tương đối mới với lập trình, sẽ chiếm 98,7% hoặc nhiều hơn trong toàn bộ thời gian hoạt động của dự án của bạn, và người nghèo thực hiện bảo trì gần như chắc chắn sẽ là người khác ngoài bạn. Và có một cơ hội rất tốt họ sẽ dành 50% thời gian của họ vào công việc nguyền rủa tên của bạn.

Và dĩ nhiên FxCop sủa bạn và bạn phải cũng thếthêm một thuộc tính vào mã của bạn đã nén chính xác để thực hiện với chương trình đang chạy và chỉ ở đó để báo cho FxCop bỏ qua một vấn đề trong 99,9% trường hợp nó hoàn toàn chính xác trong việc gắn cờ. Và, xin lỗi, tôi có thể bị nhầm lẫn, nhưng thuộc tính "bỏ qua" đó có thực sự được biên dịch vào ứng dụng của bạn không?

Sẽ đưa toàn bộ if kiểm tra trên một dòng làm cho nó dễ đọc hơn? Tôi không nghĩ vậy. Ý tôi là, tôi đã có một lập trình viên kịch liệt khác lập luận một lần từ lâu rằng việc đưa thêm mã vào một dòng sẽ làm cho nó "chạy nhanh hơn". Nhưng tất nhiên anh ta là những hạt dẻ. Cố gắng giải thích cho anh ta (với khuôn mặt thẳng thắn - đó là một thử thách) làm thế nào thông dịch viên hoặc trình biên dịch sẽ phá vỡ đường dài đó thành các câu lệnh riêng lẻ trên mỗi dòng - về cơ bản giống với kết quả nếu anh ta đi trước và chỉ làm cho mã có thể đọc được thay vì cố gắng vượt qua trình biên dịch - không ảnh hưởng gì đến anh ta. Nhưng tôi lạc đề.

Bao nhiêu ít hơn có thể đọc được điều này khi bạn thêm ba loại ngoại lệ khác, một hoặc hai tháng kể từ bây giờ? (Trả lời: nó nhận được một nhiều ít có thể đọc được).

Một trong những điểm chính, thực sự, là hầu hết các điểm định dạng mã nguồn văn bản mà tất cả chúng ta đang tìm kiếm mỗi ngày là làm cho nó thực sự, thực sự hiển nhiên đối với những con người khác những gì đang thực sự xảy ra khi mã chạy. Bởi vì trình biên dịch biến mã nguồn thành một cái gì đó hoàn toàn khác và không thể quan tâm ít hơn đến kiểu định dạng mã của bạn. Vì vậy, tất cả-trên-một dòng hoàn toàn hút, quá.

Chỉ cần nói ...

// super sucks...
catch( Exception ex )
{
    if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

370
2017-10-12 00:24



Khi tôi lần đầu tiên vấp phải câu hỏi này, tôi đã vượt qua câu trả lời được chấp nhận. Cool Tôi chỉ có thể bắt tất cả Exceptionvà kiểm tra loại. Tôi nghĩ nó đã làm sạch mã, nhưng cái gì đó khiến tôi quay lại câu hỏi và tôi thực sự đọc các câu trả lời khác cho câu hỏi. Tôi nhai nó một lúc, nhưng tôi phải đồng ý với bạn. Nó là hơn có thể đọc và duy trì để sử dụng chức năng làm khô mã của bạn hơn là bắt tất cả mọi thứ, kiểm tra loại so sánh với danh sách, mã bao gói và ném. Cảm ơn bạn đã đến trễ và cung cấp tùy chọn thay thế và lành mạnh (IMO). +1. - erroric
Sử dụng chức năng xử lý lỗi sẽ không hoạt động nếu bạn muốn bao gồm throw;. Bạn sẽ phải lặp lại dòng mã đó trong mỗi khối catch (rõ ràng không phải là kết thúc của thế giới nhưng đáng nói đến vì nó là mã cần lặp lại). - kad81
@ kad81, đó là sự thật, nhưng bạn vẫn sẽ nhận được lợi ích của việc ghi nhật ký và mã dọn dẹp ở một nơi và thay đổi nó ở một nơi nếu cần thiết, không có ngữ nghĩa ngốc nghếch khi bắt loại ngoại lệ cơ bản sau đó phân nhánh dựa trên loại ngoại lệ. Và thêm một throw();tuyên bố trong mỗi khối catch là một mức giá nhỏ để thanh toán, IMO, và vẫn để lại cho bạn ở vị trí để làm thêm loại trừ cụ thể ngoại lệ nếu cần thiết. - Craig
Xin chào @Reitffunk, chỉ cần sử dụng Func<Exception, MyEnumType> thay vì Action<Exception>. Đó là Func<T, Result>, với Result là kiểu trả về. - Craig
Tôi hoàn toàn đồng ý ở đây. Tôi cũng đọc câu trả lời đầu tiên và suy nghĩ có vẻ hợp lý. Đã chuyển đến một generic 1 cho tất cả các trình xử lý ngoại lệ. Một cái gì đó bên trong tôi làm tôi rối loạn nội bộ ... vì vậy tôi đã hoàn nguyên mã. Sau đó, đi qua vẻ đẹp này! Điều này nhu cầu là câu trả lời được chấp nhận - Conor Gallagher


Như những người khác đã chỉ ra, bạn có thể có if tuyên bố bên trong khối catch của bạn để xác định những gì đang xảy ra. C # 6 hỗ trợ Bộ lọc ngoại lệ, do đó, các tính năng sau sẽ hoạt động:

try { … }
catch (Exception e) when (MyFilter(e))
{
    …
}

Các MyFilter phương pháp sau đó có thể trông giống như sau:

private bool MyFilter(Exception e)
{
  return e is ArgumentNullException || e is FormatException;
}

Ngoài ra, điều này có thể được thực hiện tất cả nội tuyến (phía bên tay phải của tuyên bố khi chỉ cần có một biểu thức boolean).

try { … }
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
    …
}

Điều này khác với việc sử dụng if tuyên bố từ bên trong catch chặn, sử dụng bộ lọc ngoại lệ sẽ không thư giãn ngăn xếp.

Bạn có thể tải về Visual Studio 2015 để kiểm tra điều này.

Nếu bạn muốn tiếp tục sử dụng Visual Studio 2013, bạn có thể cài đặt gói nuget sau:

Gói cài đặt Microsoft.Net.Compilers

Vào thời điểm viết bài, điều này sẽ bao gồm hỗ trợ cho C # 6.

Tham chiếu gói này sẽ làm cho dự án được xây dựng bằng cách sử dụng   phiên bản cụ thể của trình biên dịch C # và Visual Basic chứa trong   gói, trái với bất kỳ phiên bản cài đặt hệ thống nào.


241
2018-04-04 13:59



Kiên nhẫn chờ đợi phát hành chính thức của 6 ... Tôi muốn thấy điều này có được kiểm tra khi điều đó xảy ra. - RubberDuck
@RubberDuck Tôi đang chết cho nhà điều hành truyền bá null từ C # 6. Cố gắng thuyết phục phần còn lại của nhóm của tôi rằng nguy cơ của một ngôn ngữ không ổn định / trình biên dịch là giá trị nó. Rất nhiều cải tiến nhỏ với tác động rất lớn. Để nhận được đánh dấu là câu trả lời, không quan trọng, miễn là mọi người nhận ra điều này sẽ / là có thể, tôi hạnh phúc. - Joe
Đúng?! Tôi sẽ xem xét kỹ cơ sở mã của tôi trong tương lai gần. =) Tôi biết việc kiểm tra là không quan trọng, nhưng với câu trả lời được chấp nhận sẽ sớm bị lỗi thời, tôi hy vọng OP quay trở lại để kiểm tra điều này để cung cấp cho nó khả năng hiển thị thích hợp. - RubberDuck
Đó là một phần lý do tại sao tôi chưa trao nó @Joe. Tôi muốn điều này được hiển thị. Bạn có thể muốn thêm một ví dụ về một bộ lọc nội tuyến cho rõ ràng. - RubberDuck


Không phải trong C # không may, vì bạn cần một bộ lọc ngoại lệ để làm điều đó và C # không trưng ra tính năng đó của MSIL. VB.NET có khả năng này mặc dù, ví dụ:

Catch ex As Exception When TypeOf ex Is FormatException OrElse TypeOf ex Is OverflowException

Những gì bạn có thể làm là sử dụng một hàm ẩn danh để đóng gói mã lỗi của bạn và sau đó gọi nó trong các khối catch cụ thể đó:

Action onError = () => WebId = Guid.Empty;
try
{
    // something
}
catch (FormatException)
{
    onError();
}
catch (OverflowException)
{
    onError();
}

184
2017-09-25 21:03



Ý tưởng thú vị và một ví dụ khác mà VB.net có một số lợi thế thú vị trên C # đôi khi - Michael Stum♦
@MichaelStum với cái đó loại cú pháp tôi hầu như không gọi nó là thú vị chút nào ... rùng mình - MarioDS
Các bộ lọc ngoại lệ đang đến trong c # 6! Lưu ý sự khác biệt của việc sử dụng các bộ lọc có lợi cho việc tái sử dụng roslyn.codeplex.com/discussions/541301 - Arne Deruwe
@ArneDeruwe Cảm ơn bạn đã liên kết! Tôi vừa học thêm một lý do quan trọng nữa là không nên ném lại: throw e; phá hủy stacktrace và callstack, throw; phá hủy callstack "chỉ" (hiển thị đổ vỡ-dumps vô dụng!) A rất lý do tốt để sử dụng không nếu nó có thể tránh được! - AnorZaken
Nếu tôi không nhầm lẫn bạn cũng có thể thả qua một nắm bắt trong VB như bạn có thể với trường hợp hoặc (chuyển đổi trong c #) báo cáo như vậy Try Catch ex As ArgumentException Catch ex As NullReferenceException End Try Nhưng tiếc là C # không vì vậy chúng tôi còn lại với một phương pháp trợ giúp hoặc để nắm bắt chung và xác định loại. - David Carrigan


Vì lợi ích của sự hoàn chỉnh, vì .NET 4.0mã có thể viết lại là:

Guid.TryParse(queryString["web"], out WebId);

TryParse không bao giờ ném ngoại lệ và trả về false nếu định dạng sai, thiết lập WebId thành Guid.Empty.


C # 7 bạn có thể tránh giới thiệu một biến trên một dòng riêng biệt:

Guid.TryParse(queryString["web"], out Guid webId);

Bạn cũng có thể tạo các phương thức để phân tích các bộ dữ liệu trả về, không có sẵn trong .NET Framework kể từ phiên bản 4.6:

(bool success, Guid result) TryParseGuid(string input) =>
    (Guid.TryParse(input, out Guid result), result);

Và sử dụng chúng như thế này:

WebId = TryParseGuid(queryString["web"]).result;
// or
var tuple = TryParseGuid(queryString["web"]);
WebId = tuple.success ? tuple.result : DefaultWebId;

Bản cập nhật vô dụng tiếp theo cho câu trả lời vô ích này đến khi việc giải mã các tham số ngoài được thực hiện trong C # 12. :)


123
2018-04-13 12:18



Chính xác - ngắn gọn và bạn hoàn toàn bỏ qua hình phạt xử lý ngoại lệ, hình thức xấu cố ý sử dụng ngoại lệ để kiểm soát luồng chương trình và trọng tâm mềm của việc chuyển đổi logic của bạn, một chút ở đây và một chút . - Craig
Tôi biết ý bạn là gì, nhưng tất nhiên Guid.TryParse không bao giờ trở lại Guid.Empty. Nếu chuỗi có định dạng không đúng, chuỗi sẽ đặt result thông số đầu ra cho Guid.Empty, Nhưng nó trả về  false. Tôi đang đề cập đến nó bởi vì tôi đã nhìn thấy mã làm mọi thứ theo phong cách Guid.TryParse(s, out guid); if (guid == Guid.Empty) { /* handle invalid s */ }, thường là sai nếu s có thể là biểu diễn chuỗi Guid.Empty. - hvd
wow bạn đã trả lời câu hỏi, ngoại trừ việc nó không ở trong tinh thần của câu hỏi. Vấn đề lớn hơn là một cái gì đó khác :( - nawfal
Các mô hình thích hợp để sử dụng TryParse, tất nhiên, là giống như if( Guid.TryParse(s, out guid){ /* success! */ } else { /* handle invalid s */ }, mà không để lại sự mơ hồ như ví dụ bị hỏng trong đó giá trị đầu vào thực sự có thể là biểu diễn chuỗi của một Guid. - Craig
Câu trả lời này thực sự có thể đúng đối với Guid.Parse, nhưng nó đã bỏ lỡ toàn bộ điểm của câu hỏi gốc. Mà không có gì để làm với Guid.Parse, nhưng là liên quan đến việc bắt Exception vs FormatException / OverflowException / etc. - Conor Gallagher


Nếu bạn có thể nâng cấp ứng dụng của mình lên C # 6 thì bạn thật may mắn. Phiên bản C # mới đã triển khai các bộ lọc Ngoại lệ. Vì vậy, bạn có thể viết điều này:

catch (Exception ex) when (ex is FormatException || ex is OverflowException) {
    WebId = Guid.Empty;
}

Một số người nghĩ rằng mã này giống như

catch (Exception ex) {                
    if (ex is FormatException || ex is OverflowException) {
        WebId = Guid.Empty;
    }
    throw;
}

Nhưng không phải vậy. Trên thực tế đây là tính năng mới duy nhất trong C # 6 mà không thể mô phỏng trong các phiên bản trước. Đầu tiên, việc ném lại có nghĩa là chi phí cao hơn bỏ qua việc bắt. Thứ hai, nó không tương đương về mặt ngữ nghĩa. Tính năng mới giữ nguyên ngăn xếp nguyên vẹn khi bạn đang gỡ lỗi mã của mình. Nếu không có tính năng này, sự cố kết xuất không hữu ích hoặc thậm chí vô dụng.

Thấy một thảo luận về điều này trên CodePlex. Và một ví dụ cho thấy sự khác biệt.


62
2018-04-01 12:29



Ném mà không có ngoại lệ bảo tồn ngăn xếp, nhưng "ném cũ" sẽ ghi đè lên nó. - Ivan


Nếu bạn không muốn sử dụng if tuyên bố trong catch phạm vi, trong C# 6.0 bạn có thể dùng Exception Filters cú pháp đã được CLR hỗ trợ trong các phiên bản xem trước nhưng chỉ tồn tại trong VB.NET/MSIL:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (Exception exception) when (exception is FormatException || ex is OverflowException)
{
    WebId = Guid.Empty;
}

Mã này sẽ bắt Exception chỉ khi đó là InvalidDataException hoặc là ArgumentNullException.

Trên thực tế, bạn có thể đặt cơ bản bất kỳ điều kiện nào bên trong when mệnh đề:

static int a = 8;

...

catch (Exception exception) when (exception is InvalidDataException && a == 8)
{
    Console.WriteLine("Catch");
}

Lưu ý rằng trái ngược với if tuyên bố bên trong catchphạm vi của, Exception Filters không thể ném Exceptionsvà khi nào, hoặc khi điều kiện không true, tiếp theo catch điều kiện sẽ được đánh giá thay thế:

static int a = 7;

static int b = 0;

...

try
{
    throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
    Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
    Console.WriteLine("General catch");
}

Đầu ra: Tổng quát.

Khi có nhiều thì một true  Exception Filter - người đầu tiên sẽ được chấp nhận:

static int a = 8;

static int b = 4;

...

try
{
    throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
    Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
    Console.WriteLine("General catch");
}

Đầu ra: Catch.

Và như bạn có thể thấy trong MSIL mã không được dịch sang if báo cáo, nhưng để FiltersExceptions không thể ném từ bên trong khu vực được đánh dấu bằng Filter 1 và Filter 2 nhưng bộ lọc ném Exception sẽ thất bại thay vào đó, cũng là giá trị so sánh cuối cùng được đẩy vào ngăn xếp trước endfilter lệnh sẽ xác định thành công / thất bại của bộ lọc (Catch 1  XOR  Catch 2 sẽ thực hiện tương ứng):

Exception Filters MSIL

Ngoài ra, cụ thể Guid có Guid.TryParse phương pháp.


26
2017-10-07 17:31





Câu trả lời được chấp nhận có vẻ chấp nhận được, ngoại trừ CodeAnalysis /FxCop sẽ phàn nàn về thực tế là nó đang bắt một loại ngoại lệ chung.

Ngoài ra, có vẻ như toán tử "is" có thể làm giảm hiệu suất một chút.

CA1800: Không cast không cần thiết nói "xem xét thử nghiệm kết quả của toán tử 'as' thay thế", nhưng nếu bạn làm điều đó, bạn sẽ viết nhiều mã hơn nếu bạn bắt từng ngoại lệ riêng biệt.

Nhưng dù sao, đây là những gì tôi sẽ làm:

bool exThrown = false;

try
{
    // Something
}
catch (FormatException) {
    exThrown = true;
}
catch (OverflowException) {
    exThrown = true;
}

if (exThrown)
{
    // Something else
}

19
2017-07-30 17:09



Nhưng lưu ý rằng bạn không thể tính lại ngoại lệ mà không làm mất dấu vết ngăn xếp nếu bạn làm như thế này. (Xem bình luận của Michael Stum về câu trả lời được chấp nhận) - René
Mô hình này có thể được cải thiện bằng cách lưu trữ ngoại lệ (vui lòng giải thích định dạng kém - Tôi không thể tìm ra cách đặt mã trong các nhận xét): Ngoại lệ ex = null; thử {// something} catch (FormatException e) {ex = e; } catch (OverflowException e) {ex = e; } if (ex! = null) {// cái gì khác và đối phó với ex} - Jesse Weigert
@ JesseWeigert: 1. Bạn có thể sử dụng backticks để cung cấp cho một đoạn văn bản một phông chữ đơn cách và nền xám nhạt. 2. Bạn vẫn sẽ không thể tính lại ngoại lệ ban đầu bao gồm cả stacktrace. - Oliver
@CleverNeologism mặc dù có thể đúng là sử dụng is nhà điều hành có thể có một tác động tiêu cực nhẹ đến hiệu suất, nó cũng đúng là một xử lý ngoại lệ không phải là nơi để được quá lo ngại về tối ưu hóa hiệu suất. Nếu ứng dụng của bạn dành quá nhiều thời gian vào các trình xử lý ngoại lệ, việc tối ưu hóa hiệu suất sẽ tạo ra sự khác biệt thực sự về hiệu suất ứng dụng, thì có các vấn đề về mã khác cần xem xét kỹ. Có nói rằng, tôi vẫn không thích giải pháp này bởi vì bạn mất dấu vết ngăn xếp và bởi vì dọn dẹp được loại bỏ theo ngữ cảnh từ câu lệnh bắt. - Craig
Thời gian duy nhất is nhà điều hành làm giảm hiệu suất là nếu sau này bạn thực hiện as hoạt động (do đó họ đủ điều kiện với quy tắc không cần thiết). Nếu tất cả những gì bạn đang làm là thử nghiệm dàn diễn viên mà không cần thực hiện dàn diễn viên, thì is toán tử là chính xác những gì bạn muốn sử dụng. - saluce


Đây là một biến thể của câu trả lời của Matt (tôi cảm thấy rằng đây là một chút sạch hơn) ... sử dụng một phương pháp:

public void TryCatch(...)
{
    try
    {
       // something
       return;
    }
    catch (FormatException) {}
    catch (OverflowException) {}

    WebId = Guid.Empty;
}

Bất kỳ ngoại lệ nào khác sẽ được ném và mã WebId = Guid.Empty; sẽ không bị đánh trúng. Nếu bạn không muốn các ngoại lệ khác làm hỏng chương trình của mình, chỉ cần thêm vào sau hai lần bắt giữ khác:

...
catch (Exception)
{
     // something, if anything
     return; // only need this if you follow the example I gave and put it all in a method
}

18
2017-08-31 20:51



-1 Điều này sẽ thực hiện WebId = Guid.Emtpy trong trường hợp không có ngoại lệ. - Sepster
@sepster Tôi nghĩ rằng câu lệnh trả về sau "// something" được ngụ ý ở đây. Tôi không thực sự thích giải pháp, nhưng đây là một biến thể mang tính xây dựng trong cuộc thảo luận. +1 để hoàn tác ghi chú của bạn :-) - toong
@Sepster toong là đúng, tôi giả định rằng nếu bạn muốn quay trở lại đó, bạn sẽ đặt một câu trả lời ... Tôi đã cố gắng trả lời đủ để áp dụng cho mọi tình huống trong trường hợp những người khác có câu hỏi tương tự nhưng không chính xác sẽ được hưởng lợi tốt. Tuy nhiên, để có biện pháp tốt, tôi đã thêm return với câu trả lời của tôi. Cảm ơn các đầu vào. - bsara