처분 할 것이없는 상황에서 '사용'이 적절한가?


9

C #에서 usingstatement는 가비지 수집기를 기다리지 않고 리소스를 결정적인 방식으로 처리하는 데 사용됩니다. 예를 들어, 다음과 같은 용도로 사용될 수 있습니다.

  • SQL 명령 또는 연결을 폐기하십시오.

  • 스트림을 닫고 파일처럼 기본 소스를 해제합니다.

  • 무료 GDI + 요소

  • 기타

나는 눈치 using처분 할 것이없는 곳의 경우 더 많은 사용되지만, 그것은 단지 더 편리 어디 호출자가 기록 할 using블록이 아닌 두 개의 명령을.

예 :

  • Stack Overflow 팀이 작성한 MiniProfilerusing 는 프로파일 링 할 블록을 나타내는 데 사용 합니다.

    using (profiler.Step("Name goes here"))
    {
        this.DoSomethingUseful(i - 1);
    }
    

    한 가지 대안은 두 개의 블록을 갖는 것입니다.

    var p = profiler.Start("Name goes here");
    this.DoSomethingUseful(i - 1);
    profiler.Stop(p);

    또 다른 방법은 조치를 사용하는 것입니다.

    profiler.Step("Name goes here", () => this.DoSomethingUseful(i - 1));
  • ASP.NET MVC는 다음 using과 같은 양식 도 선택 했습니다.

    <% using (Html.BeginForm())
       { %>
           <label for="firstName">Name:</label>
           <%= Html.TextBox("name")%>
           <input type="submit" value="Save" />    
    <% } %>

그러한 사용법이 적절합니까? 몇 가지 단점이 있음을 감안할 때 그것을 정당화하는 방법 :

  • 초보자는 책과 언어 사양에 설명 된 사용법과 일치하지 않으므로

  • 코드는 표현력이 있어야합니다. 표현의 어려움 using은 가비지 수집기를 기다리지 않고 해제 해야하는 스트림, 네트워크 연결 또는 데이터베이스와 같은 리소스가 있다는 것을 보여주는 것입니다.


2
두 개의 개별 문을 갖는 접근 방식은 다음과 같은 using사항이 없는 순진한 자원 관리와 같은 문제를 겪습니다 profiler.Stop(p).

1
@delnan : MiniProfiler가 두 번째 접근 방식을 피한 이유를 설명합니다. 그러나 두 번째는 작성 및 유지 관리가 어렵 기 때문에 모든 경우에 피해야합니다.
Arseni Mourzenko



답변:


7

마지막 진술- "사용의 적절한 사용법은 뒤에, 가비지 수집기를 기다리지 않고 해제 해야하는 스트림, 네트워크 연결 또는 데이터베이스와 같은 리소스가 있음을 보여주는 것입니다." IDisposable 인터페이스 설명서에 나와 있습니다. http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

이 인터페이스의 주된 용도는 관리되지 않는 리소스를 해제하는 것입니다.

따라서 클래스가 관리되지 않는 리소스를 사용하는 경우 GC가 발생하거나 원하지 않을 때 중요하지 않습니다. 관리되지 않는 리소스가 GC되지 않기 때문에 GC와는 아무런 관련이 없습니다 ( https : //.com/stackoverflow . com / questions / 3607213 / what-is-meant-by-managed-vs-unmanaged-resources-in-net ).

"사용"의 목적은 GC에서 대기 방지하기 위해되지 않도록, 그것은 그 관리되지 않는 리소스의 해제를 강제로의 현재 클래스 인스턴스가 범위를 벗어나과의 Finalize를 호출하기 전에. 관리되지 않는 리소스는 다른 관리되지 않는 리소스에 종속 될 수 있으며 잘못된 순서로 폐기 (또는 완료) 된 경우 나쁜 일이 발생할 수 있습니다.

따라서 using 블록에서 인스턴스화되는 클래스가 관리되지 않는 리소스를 사용하는 경우 응답은 예입니다. 적절합니다.

IDisposable은 관리되지 않는 리소스를 릴리스하기위한 것 일뿐 , 이것이 주된 목적 이라는 점을 규정하지는 않습니다 . 그것은 클래스의 저자들이 특정 시간에 일어나고, 그리고는 IDisposable 그 일이 얻기의 방법이 될 수 있습니다 구현 시행하고 싶지만 있는지 여부를 우아한 해결책이 몇 가지 조치를 가지고있는 경우가 그 뭔가 캔 사례별로 만 답변합니다.

어느 쪽이든, "using"의 사용은 클래스가 IDisposable을 구현한다는 것을 암시하므로 코드 표현을 위반하지 않습니다. 실제로 무슨 일이 일어나고 있는지 분명히 알 수 있습니다.


"이 인터페이스의 주요 용도는 관리되지 않는 리소스를 해제하는 것입니다." 나는 마이크로 소프트의 문서가 그 시점에서 짜증 난다고 말한다. 방법의 어쩌면 그들이 FCL을에서 사용하지만, 응용 프로그램 개발자는 이제 십 년 가까이위한 다양한 일을 위해 그것을 사용하고있다 - 좋은 이유로 일부, 그다지 좋지 않은 이유에 대한 몇 가지. 그러나 그들의 의사의 청크를 인용한다고해서 OP의 질문에 전혀 대답하지는 않습니다.
Jesse C. Slicer

1
두 번째 마지막 단락을 주목하십시오- 주요 목적은 유일한 목적 일 필요는 없습니다 . IDisposable은 어떤 이유로 든 구현할 수 있으며 예상되는 동작 및 사용 스타일을 가진 알려진 인터페이스를 제공하므로 인스턴스가 범위를 벗어나기 전에 발생해야 할 다른 사항이 있음을 알 수 있습니다. 요점은 : IDisposable을 구현한다면 사용하는 것이 적절하다. 다른 모든 것은 단지 서문입니다.
Maximus Minimus

1
당신은 기본적으로 목적이 GC를 기다리는 것을 피하는 것이 아니라 파이널 라이저를 기다리는 것을 피한다고 말합니다. 그러나 차이점은 없습니다. 파이널 라이저는 GC에 의해 호출됩니다.
svick

GC는 비 결정적 방식으로 작동하므로 언제 호출할지 모릅니다. GC는 또한 finalizer를 호출하지만 자체 처리는 수행하지 않습니다. 실제 자원 자체는 GC의 통제 범위를 벗어납니다. (1) 객체의 범위가 적절하고 (2) 처리가 알려진 시점에서 발생하는 것으로 알려져 있습니다.-사용 블록의 범위를 벗어나면 관리되지 않는 리소스가 사라집니다 (또는 최악의 경우) 그것을 파괴 할 다른 것으로 넘어갑니다). 실제로 이것은 단지 nitpicking입니다. 설명서를 읽으면 반복 할 필요가 없습니다.
Maximus Minimus

8

사용은 방법 using의 존재 를 의미합니다 Dispose(). 다른 프로그래머는 그러한 방법이 객체에 있다고 가정합니다. 따라서 개체를 일회용으로 사용할 수 없으면 사용해서는 안됩니다 using.

코드 선명도가 왕입니다. 을 생략 using하거나 IDisposable객체를 구현 하십시오.

MiniProfiler가 using프로파일 링중인 코드를 "울타리"하는 메커니즘 으로 사용하는 것 같습니다. 이것에는 몇 가지 장점이 있습니다. 아마도 MiniProfiler가 Dispose()타이머 중지를 위해 호출 중이거나 MiniProfiler 객체가 범위를 벗어날 때 타이머가 중지 된 것 같습니다.

더 일반적으로 using어떤 종류의 마무리가 자동으로 수행되어야 할 때 호출 합니다. 설명서 html.BeginForm는, 상기 방법이 사용되는 경우 주 using문이 폐쇄 렌더링 </form>의 끝 태그 using블록.

그렇다고해서 그것이 여전히 학대가 아님을 의미하는 것은 아닙니다.


4
지금까지는 분명했습니다. 문제는, 때 (만약 전혀)는 구현에 적합한 있습니다 IDisposable/ Dispose()묘사하고 감지 영업 이익 처분 아무것도 가지고 있지에도 불구하고?

2
나는 그것을 분명하게 생각했다. 이 없는 즉 적합한 시간.
Robert Harvey

1
내 요점은 (적절한 지 여부에 관계없이) 전혀 이해 Dispose가 필요하다는 것입니다 using. OP의 예제는 모두 구현 Dispose하지 않습니까? 그리고 IIUC, 문제는 Dispose다른 클래스 ( Stop()MiniProfiler 와 같은)보다는 이러한 클래스가 올바른지 여부 입니다.

1
예, 그러나 그것은 질문이 아닙니다. 문제는 그렇게하는 것이 좋은 아이디어인지에 관한 것입니다.

2
@delnan : 다시 말하지만, 나는 그것을 분명하게 생각했습니다. 코드의 의도를 더 명확하게하는 것이 좋습니다. 그렇지 않은 경우 그렇지 않습니다.
Robert Harvey

1

using오류 및 예외 안전입니다. 그것은 보장 Dispose()프로그래머가 만드는 어떤 실수를 선명하게 촬상 호출됩니다. 예외 포착 또는 처리를 방해하지 않지만 Dispose()예외가 발생 하면 메소드가 스택에서 반복적으로 실행됩니다.

구현 IDispose되었지만 완료되면 폐기 할 대상이없는 객체입니다 . 최선을 다해 설계를 교정하십시오. 따라서 소스 코드를 리팩터링 할 필요가 없으므로 나중에 폐기해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.