같은 클래스 Stream
, StreamReader
, StreamWriter
등을 구현하는 IDisposable
인터페이스를 제공합니다. 즉, Dispose()
이러한 클래스의 객체에서 메소드를 호출 할 수 있습니다. 또한 public
라는 메소드를 정의했습니다 Close()
. 이제 객체로 작업을 마치면 무엇을 호출해야하는지에 대해 혼동됩니다. 둘 다 호출하면 어떻게됩니까?
내 현재 코드는 다음과 같습니다
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
using (StreamWriter writer = new StreamWriter(filename))
{
int chunkSize = 1024;
while (!reader.EndOfStream)
{
char[] buffer = new char[chunkSize];
int count = reader.Read(buffer, 0, chunkSize);
if (count != 0)
{
writer.Write(buffer, 0, count);
}
}
writer.Close();
}
reader.Close();
}
}
보시다시피, 각 객체에서 using()
자동으로 Dispose()
메소드를 호출하는 구문을 작성했습니다 . 그러나 나는 또한 Close()
메소드 를 호출 합니다. 맞아?
스트림 객체를 사용할 때 모범 사례를 제안하십시오. 🙂
MSDN 예제는 using()
구문을 사용하지 않고 Close()
메소드를 호출 합니다.
좋은가요?
답변
Reflector.NET으로 빠르게 점프하면 Close()
방법 StreamWriter
이 다음과 같습니다.
public override void Close()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
그리고 StreamReader
:
public override void Close()
{
this.Dispose(true);
}
Dispose(bool disposing)
에서 무시 StreamReader
된다
protected override void Dispose(bool disposing)
{
try
{
if ((this.Closable && disposing) && (this.stream != null))
{
this.stream.Close();
}
}
finally
{
if (this.Closable && (this.stream != null))
{
this.stream = null;
/* deleted for brevity */
base.Dispose(disposing);
}
}
}
StreamWriter
방법은 비슷합니다.
그래서, 코드를 읽는 것은 그것이 분명 당신이 호출 할 수있는 Close()
& Dispose()
좋아하고 어떤 순서로 당신만큼 자주 스트림에. 어떤 식 으로든 동작을 변경하지 않습니다.
그래서 그것을 사용하는 것이 더 읽을 수 있는지 여부에 내려 오는 Dispose()
, Close()
및 / 또는 using ( ... ) { ... }
.
개인적으로 선호하는 것은 using ( ... ) { ... }
가위로 달리지 않는 데 도움이되므로 가능하면 항상 사용하는 것이 좋습니다.
그러나 이것은 정확성에 도움이되지만 가독성은 떨어집니다. C #에는 이미 중괄호를 닫는 것이 너무 많으므로 실제로 어느 것이 스트림에서 클로즈를 수행하는지 어떻게 알 수 있습니까?
그래서 나는 이것을하는 것이 가장 좋다고 생각합니다.
using (var stream = ...)
{
/* code */
stream.Close();
}
코드 동작에는 영향을 미치지 않지만 가독성에 도움이됩니다.
답변
아니요, 해당 메소드를 수동으로 호출해서는 안됩니다. using
블록 이 끝나면 Dispose()
관리되지 않는 리소스를 확보하는 데 도움이 되는 메서드가 자동으로 호출됩니다 (적어도 스트림, 리더 / 라이터 등의 표준 .NET BCL 클래스의 경우). 따라서 다음과 같이 코드를 작성할 수도 있습니다.
using (Stream responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
using (StreamWriter writer = new StreamWriter(filename))
{
int chunkSize = 1024;
while (!reader.EndOfStream)
{
char[] buffer = new char[chunkSize];
int count = reader.Read(buffer, 0, chunkSize);
if (count != 0)
{
writer.Write(buffer, 0, count);
}
}
}
이 Close()
메소드는를 호출합니다 Dispose()
.
답변
문서에 따르면이 두 가지 방법은 동일합니다.
StreamReader.Close :이 Close 구현은 True 값을 전달하는 Dispose 메서드를 호출합니다.
StreamWriter.Close :이 Close 구현은 True 값을 전달하는 Dispose 메서드를 호출합니다.
Stream.Close :이 메서드는 Dispose를 호출하여 true를 지정하여 모든 리소스를 해제합니다.
따라서 둘 다 동일하게 유효합니다.
/* Option 1, implicitly calling Dispose */
using (StreamWriter writer = new StreamWriter(filename)) {
// do something
}
/* Option 2, explicitly calling Close */
StreamWriter writer = new StreamWriter(filename)
try {
// do something
}
finally {
writer.Close();
}
개인적으로, 나는 “노이즈”가 적기 때문에 첫 번째 옵션을 고수했습니다.
답변
모두 지원하는 많은 클래스에 Close()
와 Dispose()
방법을 두 통화는 상당 할 것이다. 그러나 일부 클래스에서는 닫힌 객체를 다시 열 수 있습니다. 이러한 클래스 중 일부는 재 개설을 허용하기 위해 종료 후 일부 리소스를 유지할 수 있습니다. 다른 것들은 어떤 자원도 살아있게 유지할 수 없지만 명시 적으로 재개를 금지 Close()
하도록 플래그를 설정할 수 있습니다 Dispose()
.
에 대한 계약은 IDisposable.Dispose
명시 적으로 다시는 사용되지 않는 객체에서 호출하면 최악의 피해를 입지 않도록 요구하므로 모든 객체에서 IDisposable.Dispose
호출되는 메소드 또는 호출하지 않는 메소드를 호출하는 것이 좋습니다 .Dispose()
IDisposable
Close()
답변
이것은 오래된 질문이지만 이제 각 질문을 차단하지 않고도 문을 사용하여 작성할 수 있습니다. 포함 블록이 완료되면 역순으로 폐기됩니다.
using var responseStream = response.GetResponseStream();
using var reader = new StreamReader(responseStream);
using var writer = new StreamWriter(filename);
int chunkSize = 1024;
while (!reader.EndOfStream)
{
char[] buffer = new char[chunkSize];
int count = reader.Read(buffer, 0, chunkSize);
if (count != 0)
{
writer.Write(buffer, 0, count);
}
}
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/using