문제

주로 C ++ 개발자가 부재합니다 RAII (자원 획득은 초기화입니다) Java에서 .net은 항상 나를 괴롭 혔습니다. 청소의 onus가 클래스 작가에서 소비자로 옮겨 졌다는 사실 try finally 또는 .NET 's using 건설하다)는 현저히 열등한 것 같습니다.

Java에서 모든 물체가 힙에 있고 쓰레기 수집기가 본질적으로 결정 론적 파괴를 지원하지 않기 때문에 RAII에 대한 지원이없는 이유를 알 수 있습니다.struct) 우리는 Raii에 대한 완벽한 후보를 가지고 있습니다. 스택에서 생성 된 값 유형은 잘 정의 된 범위를 가지고 있으며 C ++ 소멸자 의미를 사용할 수 있습니다. 그러나 CLR은 값 유형에 소멸자가 있도록 허용하지 않습니다.

내 임의의 검색에서 값 유형이라면 박스형 그것은 쓰레기 수집가의 관할권에 해당되므로 그 파괴는 비 결정적이됩니다. 나는이 주장이 충분히 강하지 않다고 생각합니다. Raii의 이점은 소멸자가있는 가치 유형을 박스를 만들 수 없거나 클래스 멤버로 사용될 수 없다고 말할만큼 충분히 큽니다.

짧은 이야기를 짧게 자르려면 내 질문이 있습니다: RAII를 .NET에 소개하기 위해 값 유형을 사용할 수없는 다른 이유가 있습니까? (또는 Raii의 명백한 장점에 대한 나의 주장이 결함이 있다고 생각하십니까?)

편집하다: 처음 네 개의 답변이 요점을 놓친 이후로 질문을 명확하게 표현하지 않았을 것입니다. 나 알다 ~에 대한 Finalize 그리고 그것의 비 결정적 특성, 나는에 대해 알고 있습니다 using 구성과 나는이 두 가지 옵션이 Raii보다 열등하다고 생각합니다. using 수업 소비자가 기억해야 할 또 하나의 것입니다 (얼마나 많은 사람들이 StreamReader 안에 using 차단하다?). 내 질문은 언어 디자인에 대한 철학적 인 것입니다. 왜 그것이 그 방식이고 개선 될 수 있습니까?

예를 들어, 일반적인 결정적으로 파괴 가능한 가치 유형으로 using 그리고 lock 키워드 중복 (라이브러리 클래스에서 달성 가능) :

    public struct Disposer<T> where T : IDisposable
    {
        T val;
        public Disposer(T t) { val = t; }
        public T Value { get { return val; } }
        ~Disposer()  // Currently illegal 
        {
            if (val != default(T))
                val.Dispose();
        }
    }

나는 도울 수는 없지만 한 번 본 아프로 포스 인용문으로 끝났지 만 현재는 그 기원을 찾을 수 없다.

차가운 죽은 손이 범위를 벗어나면 내 결정 론적 파괴를 취할 수 있습니다. -

도움이 되었습니까?

해결책

더 나은 제목은 "C#/VB에 RAII가없는 이유"입니다. C ++/CLI (C ++로 관리 된 낙태의 진화)는 C ++와 동일한 의미에서 RAII를 갖습니다. 그것은 나머지 CLI 언어가 사용하는 것과 동일한 최종화 패턴에 대한 구문 설탕 (C ++/CLI의 관리 대상의 파괴자)이지만, 그곳에 있습니다.

당신은 좋아할 것입니다 http://blogs.msdn.com/hsutter/archive/2004/07/31/203137.aspx

다른 팁

훌륭한 질문과 나를 크게 괴롭힌 질문. Raii의 이점은 매우 다르게 인식되는 것으로 보입니다. .NET에 대한 나의 경험에서, 결정 론적 (또는 적어도 신뢰할 수있는) 리소스 수집의 부족은 주요 단점 중 하나입니다. 사실, .NET은 저에게 여러 번 나에게 전체 아키텍처를 사용하여 관리되지 않는 자원을 다루도록 강요했습니다. ~할 것 같다 (그러나) 명시적인 수집이 필요하지 않을 수 있습니다. 물론 전체 아키텍처를 더욱 어렵게 만들고 고객의 관심을 더 중심적인 측면에서 멀어지게하기 때문에 큰 단점입니다.

브라이언 해리 (Brian Harry)는 이론적 근거에 대한 좋은 게시물을 가지고 있습니다 여기.

여기에 발췌가 있습니다.

결정 론적 결승 및 가치 유형 (Structs)은 어떻습니까?

------------ 나는 파괴자 등을 가진 structs에 대해 많은 질문을 보았습니다. 이것은 논평 가치가 있습니다. 왜 일부 언어에 그것들이 없는지에 대한 다양한 문제가 있습니다.

(1) 구성 - 위에서 설명한 것과 동일한 종류의 구성 이유에 대해 일반적인 경우에 결정 론적 수명을 제공하지 않습니다. 어쨌든 GC에 의해 마무리 될 때까지 파괴자를 포함하는 비 결정적 등급은 파괴자를 부르지 않을 것입니다.

(2) 복사 생성자 - 정말로 좋을 곳은 스택에 할당 된 현지인입니다. 그것들은 그 방법에 비난을 받고 모든 것이 좋을 것입니다. 불행히도, 이것을 실제로 작동시키기 위해서는 인스턴스가 복사 될 때마다 복사 생성자를 추가하고 호출해야합니다. 이것은 C ++에서 가장 추악하고 가장 복잡한 것 중 하나입니다. 당신은 당신이 그것을 기대하지 않는 곳에서 코드를 실행하게됩니다. 그것은 많은 언어 문제를 일으킨다. 일부 언어 디자이너는 이로부터 멀리하기로 선택했습니다.

우리는 소멸자로 구조를 만들었지 만 위의 문제에 직면하여 행동을 합리적으로 만들기 위해 많은 제한을 추가했다고 가정 해 봅시다. 제한은 다음과 같습니다.

(1) 로컬 변수로만 선언 할 수 있습니다.

(2) 당신은 그것들을 레프로만 통과시킬 수 있습니다

(3) 할당 할 수 없으며 필드에만 액세스하고 메소드를 호출 할 수 있습니다.

(4) 당신은 그들을 상자에 넣을 수 없습니다.

(5) 반사 (늦은 바인딩)를 통해 그것들을 사용하는 문제는 일반적으로 권투가 포함되기 때문입니다.

어쩌면 더, 그러나 그것은 좋은 출발입니다.

이런 것들은 어떤 용도일까요? 실제로 로컬 변수로만 사용할 수있는 파일 또는 데이터베이스 연결 클래스를 생성 하시겠습니까? 나는 아무도 정말로 믿지 않는다. 대신에하는 일은 범용 연결을 만들고 스코프 로컬 변수로 사용하기 위해 자동 파괴 래퍼를 만드는 것입니다. 그런 다음 발신자는 사용하고 싶은 것을 선택했습니다. 발신자는 결정을 내렸고 객체 자체에 완전히 캡슐화되지는 않았습니다. 몇 가지 섹션에서 제기되는 제안과 같은 것을 사용할 수 있다는 점을 감안할 때.

.NET에서 RAII를 대체하는 것은 사용 패턴이며, 일단 익숙해지면 거의 작동합니다.

가장 가까운 것은 매우 제한된 StackAlloc 연산자입니다.

당신이 그들을 검색하는 경우 유사한 스레드가 있지만 기본적으로 요약하는 것은 .NET에서 raii를 원한다면 단순히 idisposable 유형을 구현하고 "사용"명령문을 사용하여 결정 론적 처분을 얻는다는 것입니다. 이렇게하면 많은 동일한 사원을 약간 더 말로 구현하고 사용할 수 있습니다.

IMHO, vb.net과 c# 필요한 큰 것들은 다음과 같습니다.

  1. 필드에 대한 "사용"선언은 컴파일러가 태그가 붙은 모든 필드를 처리 할 코드를 생성하게합니다. 기본 동작은 컴파일러가 클래스를 구현하지 않으면 클래스를 구현하거나 여러 가지 일반적인 Idisposal 구현 패턴에 대해 주 처리 루틴을 시작하기 전에 처리 할 수없는 경우 IDISPosable을 구현해야합니다. 폐기 물건은 특정 이름으로 일상적으로 가야합니다.
  2. 생성자 및/또는 필드 초기화기가 기본 동작 (기본 폐기 방법 호출) 또는 사용자 정의 동작 (특정 이름을 가진 메소드 호출)으로 예외를 던지는 객체를 결정적으로 처분하는 수단.
  3. vb.net의 경우 모든 Weevent 필드를 무효화하기위한 자동 생성 방법.

이들 모두는 vb.net에서 꽤 잘 지낼 수 있고 C#에서는 다소 잘 어울릴 수 있지만, 일류 지원은 두 언어를 모두 개선 할 것입니다.

finalize () 메소드를 사용하여 .NET 및 Java에서 RAII 형태를 수행 할 수 있습니다. Class가 GC에 의해 클래스를 정리하기 전에 Finalize () 오버로드가 호출되므로 클래스가 절대적으로 유지해서는 안되는 리소스 (뮤트, 소켓, 파일 핸들 등)를 정리하는 데 사용할 수 있습니다. 그래도 여전히 결정 론적이지 않습니다.

.NET을 사용하면 idisposable 인터페이스 및 사용 키워드를 사용하여 결정적 으로이 중 일부를 수행 할 수 있지만 (결정 론적 동작에 필요한 경우 구성을 사용하여, 여전히 결정 론적 메모리 거래로, 클래스에서 자동으로 사용되지 않는 등) 제한 사항이 있습니다.

그렇습니다. 정확한 메커니즘은 끝없이 토론 할 수 있지만 Raii 아이디어를 .NET 및 기타 관리 언어로 소개 할 장소가 있다고 생각합니다. 내가 볼 수있는 유일한 다른 대안은 임의의 자원 정리를 처리 할 수있는 GC를 도입하는 것입니다 (메모리뿐만 아니라). 그러면 자원이 절대적으로 결정적으로 해제되어야 할 때 문제가 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top