Chỉnh sửa: Hai tùy chọn được hiển thị bên dưới.Cách tốt nhất để trả lại IDisposables được xây dựng một cách an toàn là gì?
Nếu bạn chỉ cần sử dụng chức năng mà IDisposable cung cấp, mệnh đề có tên thích hợp là using
hoạt động tốt. Nếu bạn đang gói một IDisposable
trong một đối tượng, đối tượng chứa chính nó cần phải là IDisposable
và bạn cần triển khai mẫu phù hợp (một lớp IDisposable
bị đóng kín hoặc lộn xộn hơn nhưng standard virtual
pattern).
Nhưng đôi khi một phương pháp nhà máy trợ giúp là tốt cho sự sạch sẽ. Nếu bạn trả lại IDisposable
trực tiếp sau khi xây dựng, bạn ổn, nhưng nếu trước tiên bạn xây dựng và sau đó sửa đổi hoặc thực thi mã có thể ném ngoại lệ trước khi quay trở lại, bạn cần gọi an toàn .Dispose()
- nhưng chỉ nếu có một lỗi.
Ví dụ, mã không an toàn có thể trông như thế này ...
DbCommand CreateCommandUnsafely(string commandText)
{
var newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; //what if this throws?
return newCommand;
}
Solutions Hai biến thể an toàn sau ...
DbCommand CreateCommandSafelyA(string commandText)
{
DbCommand newCommand = null;
bool success = false;
try {
newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; //if this throws...
success=true;
return newCommand;
} finally{
if (!success && newCommand != null)
newCommand.Dispose(); //...we'll clean up here.
}
}
DbCommand CreateCommandSafelyB(string commandText)
{
DbCommand newCommand = null;
try {
newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; //if this throws...
return newCommand;
} catch {
if (newCommand != null)
newCommand.Dispose(); //...we'll clean up here.
throw;
}
}
Safe biến thể A chỉ là một dòng còn là , nhưng có vẻ là cách tiếp cận thành ngữ. Có vẻ như không có bất kỳ giải pháp thực sự ngắn gọn nào, mặc dù một số áp phích bên dưới cung cấp một số tùy chọn sử dụng lambda để trích xuất gói gọn này.
Mã sưng lên với bất kỳ phương pháp an toàn trên vẫn còn, và đặc biệt tiết tăng nặng với mã mà ban đầu trông giống như ...
return new MyDisposableThing {
OptionA = "X",
OptionB = B.Blabla,
Values = src.Values.Where(priority => priority > 1.0),
};
Đoạn mã trên được viết một cách an toàn là khá lâu hơn một chút và ít có thể đọc được bởi vì bạn không còn có thể sử dụng cú pháp setter rút gọn nữa.
Điều này trông giống như mã tôi thấy ở nơi khác. Bạn có biết tại sao điều này là thích hợp hơn? –
Bắt ngoại lệ tùy ý (vì các câu trả lời khác dường như biện hộ) gây ra nhiều vấn đề trong trường hợp đặc biệt và nên tránh bất cứ khi nào có thể. Bằng cách đặt việc xử lý bên trong câu lệnh 'finally', mẫu chuẩn tránh các ngoại lệ bắt buộc, và (khi tạo đối tượng thất bại) nó bắt chước hành vi của câu lệnh' using' danh nghĩa. –