Có phải là thực tế xấu để trở về từ trong một thử bắt cuối cùng chặn?


128

Vì vậy, tôi đã bắt gặp một số mã sáng nay trông như thế này:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

Bây giờ mã này biên dịch tốt và hoạt động như bình thường, nhưng nó không cảm thấy đúng khi trở về từ trong một khối thử, đặc biệt là nếu cuối cùng có một liên kết.

Vấn đề chính của tôi là điều gì xảy ra nếu cuối cùng ném ngoại lệ của chính nó? Bạn đã có một biến trả về nhưng cũng là một ngoại lệ để xử lý ... vì vậy tôi muốn biết người khác nghĩ gì về việc quay lại từ trong một khối thử?


13
Một lợi ích của phong cách này là bạn không phải khai báo xbên ngoài trykhối. Bạn có thể giữ tuyên bố của nó gần với việc sử dụng nó.
David R Tribble

Câu trả lời:


169

Không, đó không phải là một thực hành xấu. Đặt returnnơi có ý nghĩa sẽ cải thiện khả năng đọc và bảo trì và làm cho mã của bạn đơn giản hơn để hiểu. Bạn không nên quan tâm vì finallykhối sẽ được thực thi nếu returngặp câu lệnh.


19

Cuối cùng sẽ được thực hiện bất kể điều gì, vì vậy nó không thành vấn đề.


9
Trên thực tế, không chỉ là cắm, có một số trường hợp ngoại lệ được gọi là ngoại lệ không đồng bộ như StackOverflowException, ThreadAbortException và OutOfMemoryException có thể khiến khối cuối cùng không được thực thi. Đọc về các vùng thực thi bị ràng buộc để xử lý các kịch bản này.
Mehrdad Afshari

Các liên kết này giải thích nó: return Statementthử ... bắt ... cuối cùng là Statement
amit jha

14

Cá nhân, tôi sẽ tránh loại mã hóa này vì tôi không cảm thấy muốn nhìn thấy các báo cáo trả về trước khi các tuyên bố cuối cùng.

Tâm trí của tôi rất đơn giản và nó xử lý mọi thứ khá tuyến tính. Do đó, khi tôi duyệt mã để chạy khô, tôi sẽ có xu hướng nghĩ rằng một khi tôi có thể đạt được câu lệnh return, mọi thứ sẽ không thành vấn đề, điều này rõ ràng là không đúng trong trường hợp này (không phải nó sẽ ảnh hưởng đến câu lệnh return tác dụng phụ có thể là gì).

Vì vậy, tôi sẽ sắp xếp mã để câu lệnh return luôn xuất hiện sau câu lệnh cuối cùng.


9

Điều này có thể trả lời câu hỏi của bạn

Điều gì thực sự xảy ra trong một lần thử {return x; } cuối cùng {x = null; } tuyên bố?

Từ việc đọc câu hỏi đó, có vẻ như bạn có thể có một cấu trúc thử khác trong câu lệnh cuối cùng nếu bạn nghĩ rằng nó có thể đưa ra một ngoại lệ. Trình biên dịch sẽ tìm ra khi nào trả về giá trị.

Điều đó nói rằng, tốt hơn là nên cơ cấu lại mã của bạn dù sao đi nữa để nó không gây nhầm lẫn cho bạn sau này hoặc ai đó khác có thể không biết về điều này.


hmmm rất thú vị Vì vậy, điều đó có nghĩa là nó an toàn, nhưng điều đó có nghĩa là nên tránh?
lomaxx

3
Cá nhân tôi nghĩ rằng nó làm cho khả năng đọc mã của bạn hơi khó khăn và chỉ điều đó thôi cũng đủ để tôi tìm ra một cách khác để cấu trúc mã. Nhưng thực sự đó chỉ là sở thích cá nhân.
Spencer Ruport

3
Tôi có xu hướng đồng ý với sở thích cá nhân của bạn :)
lomaxx

Tôi nghĩ rằng sự trở lại là tốt nơi nó là. Phương thức sẽ trả về giá trị, trừ khi có ngoại lệ được ném ra; không thành vấn đề nếu ngoại lệ phát sinh trong mã dọn dẹp cuối cùng.
Lawrence Dol

Lưu ý rằng hạn chế về việc trả lại từ cuối cùng không có trong Java (nhưng tôi nghĩ rằng hạn chế này là một hạn chế - kudos đối với C #).
Lawrence Dol

5

Về mặt chức năng không có sự khác biệt.

Tuy nhiên, có một lý do để không làm điều này. Các phương pháp dài hơn với một số điểm thoát thường khó đọc và phân tích hơn. Nhưng sự phản đối đó có liên quan nhiều đến các câu lệnh return hơn là bắt và cuối cùng là các khối.


Tôi sẽ thách thức điều này vì bạn có thể kết thúc với việc lồng nhiều hơn cũng khiến cho việc đọc độ phức tạp theo chu kỳ cao hơn
matt_lethargic

3

Trong ví dụ của bạn, một trong hai cách là tương đương, tôi thậm chí sẽ không ngạc nhiên nếu trình biên dịch tạo cùng một mã. Nếu một ngoại lệ xảy ra trong khối cuối cùng, bạn có cùng các vấn đề cho dù bạn đặt câu lệnh return trong khối hay bên ngoài khối đó.

Câu hỏi thực sự là theo phong cách nào là tốt nhất. Tôi thích viết các phương thức của mình để chỉ có một câu lệnh return, cách này dễ dàng hơn để thấy dòng chảy ra khỏi phương thức, theo sau tôi cũng muốn đặt câu lệnh return cuối cùng để dễ dàng nhận thấy rằng nó là kết thúc của phương thức và đây là những gì nó trả về.

Tôi nghĩ rằng với câu lệnh return được đặt rất gọn gàng như câu lệnh cuối cùng, những câu lệnh khác ít có khả năng đến và rắc nhiều câu lệnh return vào các phần khác của phương thức.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.