Có những trường hợp nào thích hợp để sử dụng try-finallykhối không có catchkhố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 trynộ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 finallykhố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 usingtừ 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 finallykhô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 finallykhô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();
}
usinglà tương đương try-finally. Bạn sẽ chỉ sử dụng try-finallykhi muốn dọn dẹp bên trong finallyvà 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 usingkhô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 finallysẽ không được thực thi.
StackOverflowExceptionhoặ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 usingcâu lệnh.
Try-[Catch]-Finallyxử 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.
usingnhư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.
tryvàfinallydưới dạng " câu lệnh try-last ."