Có những trường hợp nào thích hợp để sử dụng try-finally
khối không có catch
khối không?
Câu trả lời:
Bạn sẽ sử dụng nó để đảm bảo một số hành động xảy ra sau try
nội dung hoặc trên một ngoại lệ, nhưng khi bạn không muốn sử dụng ngoại lệ đó.
Chỉ cần rõ ràng, điều này không ẩn ngoại lệ. Các finally
khối được thực hiện trước các ngoại lệ được truyền lên các cuộc gọi stack.
Bạn cũng sẽ vô tình sử dụng nó khi bạn sử dụng using
từ khóa, vì từ khóa này biên dịch thành một try-finally
(không phải là một chuyển đổi chính xác, nhưng vì lợi ích của đối số, nó đủ gần).
try
{
TrySomeCodeThatMightException();
}
finally
{
CleanupEvenOnFailure();
}
Mã đang chạy trong finally
không được đảm bảo sẽ chạy, tuy nhiên, trường hợp không được đảm bảo là khá phức tạp - tôi thậm chí không thể nhớ nó. Tất cả những gì tôi nhớ là, nếu bạn ở trong trường hợp đó, rất có thể việc không chạy finally
không phải là vấn đề lớn nhất của bạn :-) vì vậy về cơ bản đừng đổ mồ hôi.
Cập nhật từ Tobias: finally
sẽ không chạy nếu quá trình bị ngắt.
Cập nhật từ Paddy: Các điều kiện khi cuối cùng không thực thi trong một khối .net try..finally
Ví dụ phổ biến nhất mà bạn có thể thấy là loại bỏ kết nối cơ sở dữ liệu hoặc tài nguyên bên ngoài ngay cả khi mã không thành công:
using (var conn = new SqlConnection("")) // Ignore the fact we likely use ORM ;-)
{
// Do stuff.
}
Biên dịch thành một cái gì đó như:
SqlConnection conn;
try
{
conn = new SqlConnection("");
// Do stuff.
}
finally
{
if (conn != null)
conn.Dispose();
}
using
là tương đương try-finally
. Bạn sẽ chỉ sử dụng try-finally
khi muốn dọn dẹp bên trong finally
và không quan tâm đến ngoại lệ.
Cách tiếp cận tốt nhất sẽ là
try
{
using(resource)
{
//Do something here
}
}catch(Exception)
{
//Handle Error
}
Làm như vậy ngay cả khi dọn dẹp được gọi bởi using
không thành công, mã của bạn sẽ không bị lỗi.
Có một số điều kiện khi nào finally
sẽ không được thực thi.
StackOverflowException
hoặc ExecutingEngineException
.Hy vọng điều này giải đáp nghi ngờ của bạn.
Ví dụ: nếu bạn có tài nguyên không được quản lý mà bạn tạo và sử dụng trong khối thử, bạn có thể sử dụng khối cuối cùng để đảm bảo bạn giải phóng tài nguyên đó. Khối cuối cùng sẽ luôn được thực thi bất chấp điều gì xảy ra (ví dụ: ngoại lệ) trong khối try.
Ví dụ: câu lệnh lock (x) thực sự là:
System.Threading.Monitor.Enter(x);
try { ... }
finally
{
System.Threading.Monitor.Exit(x);
}
Khối cuối cùng sẽ luôn được gọi để đảm bảo khóa độc quyền được phát hành.
Giải thích tốt bằng cách sử dụng mã:
void MyMethod1()
{
try
{
MyMethod2();
MyMethod3();
}
catch(Exception e)
{
//do something with the exception
}
}
void MyMethod2()
{
try
{
//perform actions that need cleaning up
}
finally
{
//clean up
}
}
void MyMethod3()
{
//do something
}
Nếu MyMethod2 hoặc MyMethod3 ném một ngoại lệ, nó sẽ bị MyMethod1 bắt. Tuy nhiên, mã trong MyMethod2 cần chạy mã dọn dẹp, ví dụ: đóng kết nối cơ sở dữ liệu, trước khi ngoại lệ được chuyển cho MyMethod1.
Bạn cần một khối cuối cùng, khi bất kể trường hợp ngoại lệ nào (nếu có) bị bắt hoặc thậm chí nếu không có khối nào bị bắt, bạn vẫn muốn thực thi một số mã trước khi khối thoát. Ví dụ, bạn có thể muốn đóng một tệp đang mở.
Xem Cũng thử cuối cùng
thử / cuối cùng: khi bạn không muốn xử lý bất kỳ ngoại lệ nào nhưng muốn đảm bảo (các) hành động xảy ra cho dù có hay không một ngoại lệ được đưa ra bởi mã được gọi.
Tôi không biết gì về C #, nhưng có vẻ như bất cứ điều gì bạn có thể làm với một lần thử, bạn có thể làm một cách thanh lịch hơn với một câu lệnh using . C ++ thậm chí không có cuối cùng là kết quả của RAII của nó .
try
, sau đó giảm nó trong a finally
, bạn không thể làm điều đó trong một using
câu lệnh.
Try-[Catch]-Finally
xử lý tất cả những điều đó mà không cần phải tạo một đối tượng như vậy.
using
nhưng bạn không thể thực hiện các tuyên bố chăn như bạn có. Một lần nữa, đó là xác định vấn đề bằng giải pháp, đối với tôi là ngược lại.
Đây là một tình huống mà bạn có thể muốn sử dụng, hãy thử cuối cùng: khi bạn thường sử dụng câu lệnh using, nhưng không thể vì bạn đang gọi một phương thức bằng phản xạ.
Điều này sẽ không hoạt động
using (objMsg = Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("omApp.MessagingBO")))
{
}
thay vào đó sử dụng
object objMsg = null;
try
{
objMsg
= Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("myAssembly.objBO"));
strResponse = (string)objMsg.GetType().InvokeMember("MyMethod", BindingFlags.Public
| BindingFlags.Instance | BindingFlags.InvokeMethod, null, objMsg,
new object[] { vxmlRequest.OuterXml });
}
finally
{
if (objMsg!=null)
((IDisposable)objMsg).Dispose();
}
Hãy xem liên kết sau: /software/131397/why-use-try-finally-without-a-catch-clause
Nó phụ thuộc vào kiến trúc của ứng dụng của bạn và hoạt động bạn đang thực hiện trong khối.
1. chúng ta có thể sử dụng khối try mà không cần bắt nhưng chúng ta nên sử dụng khối bắt / cuối cùng, bất kỳ một trong số chúng. 2. chúng tôi không thể sử dụng chỉ thử khối.
try
vàfinally
dưới dạng " câu lệnh try-last ."