Tôi đồng ý với câu hỏi của bạn. Vấn đề lớn nhất với tác dụng phụ có chủ ý này là khi các nhà phát triển không biết về nó và bị mù quáng theo "thực hành tốt nhất" xung quanh một StreamReader với using
. Nhưng nó có thể gây ra một số thực sự khó khăn để theo dõi lỗi khi nó là về sở hữu một đối tượng tồn tại lâu dài của, là tốt nhất (tồi tệ nhất?) Ví dụ: Tôi đã nhìn thấy là
using (var sr = new StreamReader(HttpContext.Current.Request.InputStream))
{
body = sr.ReadToEnd();
}
Các nhà phát triển không hề biết InputStream tại là hosed cho bất kỳ nơi nào trong tương lai mà hy vọng nó sẽ ở đó.
Rõ ràng, một khi bạn biết nội bộ bạn biết để tránh using
và chỉ đọc và đặt lại vị trí. Nhưng tôi nghĩ nguyên tắc cốt lõi của thiết kế API là tránh các tác dụng phụ, đặc biệt là không phá hủy dữ liệu bạn đang hành động. Không có gì vốn có về một lớp được cho là một "người đọc" nên xóa dữ liệu mà nó đọc khi thực hiện "sử dụng" nó. Việc xử lý người đọc sẽ giải phóng mọi tham chiếu đến Luồng, không tự xóa luồng. Điều duy nhất tôi có thể nghĩ là sự lựa chọn phải được thực hiện vì người đọc đang thay đổi trạng thái bên trong khác của Stream, giống như vị trí của con trỏ tìm kiếm, mà chúng giả định nếu bạn đang bao quanh một xung quanh nó. được thực hiện với mọi thứ. Mặt khác, giống như trong ví dụ của bạn, nếu bạn đang tạo một Luồng, chính luồng đó sẽ ở trong một số using
, nhưng nếu bạn đang đọc Luồng đã được tạo bên ngoài phương pháp ngay lập tức của bạn, nó sẽ là mã xóa dữ liệu.
Những gì tôi làm và nói với các nhà phát triển của chúng tôi để làm trên trường Suối rằng mã đọc không tạo ra một cách rõ ràng là ...
// save position before reading
long position = theStream.Position;
theStream.Seek(0, SeekOrigin.Begin);
// DO NOT put this StreamReader in a using, StreamReader.Dispose() clears the stream
StreamReader sr = new StreamReader(theStream);
string content = sr.ReadToEnd();
theStream.Seek(position, SeekOrigin.Begin);
(xin lỗi tôi thêm này như là một câu trả lời, sẽ không phù hợp trong một bình luận, tôi rất thích thảo luận thêm về quyết định thiết kế này của khung công tác này)
Cũng xem xét sử dụng System.IO.File.ReadAllText() trong các tình huống như thế này. Nó đơn giản hơn. –
@Dave Markle: bạn nói đúng. Tôi đã đặt nó như một ví dụ ngắn. Trên thực tế, trong mã thực, các luồng mà tôi xử lý có thể rất lớn, vì vậy đầu đọc đầu tiên đọc chúng trên mỗi dòng, sau đó luồng được sao chép trên mỗi byte sang luồng khác. –