Jon Skeet 설명에 의한 싱글 톤


214
public sealed class Singleton
{
    Singleton() {}

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested() {}
        internal static readonly Singleton instance = new Singleton();
    }
}

C #의 현재 응용 프로그램에서 Jon Skeet의 Singleton 패턴 을 구현 하고 싶습니다.

코드에 두 가지 의심이 있습니다.

  1. 중첩 클래스 내부의 외부 클래스에 액세스하는 방법은 무엇입니까? 내말은

    internal static readonly Singleton instance = new Singleton();

    폐쇄라고 불리는 것이 있습니까?

  2. 이 의견을 이해할 수 없습니다

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit

    이 의견은 우리에게 무엇을 제안합니까?


12
하하 생각 나는 조금 롤 ... 다른 존 놀란 밝혀졌다 걱정 상기했다
존 안토니 다니엘 놀란

14
두 가지가 보편적으로 받아 들여집니다. 동쪽에서 태양이 뜨고 Jon Skeet이 항상 옳습니다. 그러나 나는 아직 전자에 대해 확신하지 못한다 : P
akhil_mittal

2
@ thepirat000-그가 SO / Meta에 참여한 사람이라면 동의하지 않을 수도 있지만 실제 프로그래밍 세계에서 실제로 합법적 일 수있는 충분한 영향을 미쳤습니다. .
Code Jockey

8
이 질문의 분류법은 meta 에 대해 논의되고 있습니다.
BoltClock

답변:


359
  1. 아니요, 클로저와 관련이 없습니다. 중첩 클래스는 여기에서 개인 생성자를 포함하여 외부 클래스의 개인 멤버에 액세스 할 수 있습니다.

  2. beforefieldinit에 대한 기사를 읽으십시오 . no-op 정적 생성자를 원할 수도 있고 원하지 않을 수도 있습니다. 게으름이 필요한 것을 보장합니다. .NET 4 실제 유형 초기화 의미를 다소 변경 한다는 점을 명심해야합니다 (스펙 내에 있지만 이전보다 게으름).

당신이 할 정말 생각이 패턴을해야합니까? 당신은 도망 갈 수 없다고 확신합니까?

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();
    public static Singleton Instance { get { return instance; } }

    static Singleton() {}
    private Singleton() {}
}

12
@Anindya : 아뇨, 괜찮습니다. 당신은 :)하지만 불평 메일 JetBrains의에 할 수 있습니다
존 소총을

2
@ JonSkeet, 방금 JetBrains에 대해 우려를 제기했습니다 (# RSRP-274373). 그들이 무엇을 생각 해낼 수 있는지 봅시다. :)
Anindya Chatterjee

3
@ 달 : 당신은하지 않습니다. 단일 도메인은 AppDomain이 지속되는 동안 지속됩니다.
Jon Skeet

2
@JonSkeet Lazy<T>마법 BeforeFieldInit부작용에 대한 정적 생성자를 선언 할 필요가 없도록 사용하지 않는 이유 는 무엇입니까?
Ed T

3
FieldBeforeInit이다 MahaBharata에서Microsoft
아 미트 쿠마르 고쉬

49

질문 (1)과 관련하여 : Jon의 대답은 정확합니다. 왜냐하면 클래스를 공개 또는 내부적으로 만들지 않음으로써 암묵적으로 클래스 'Nested'를 비공개로 표시하기 때문입니다. 'private'을 추가하여 명시 적으로 수행 할 수도 있습니다.

    private class Nested

질문 (2)와 관련하여 : 기본적으로 beforeinitfield유형 초기화 에 대한 게시물은 정적 생성자가 없으면 런타임에서 언제든지 초기화 할 수 있다는 것입니다 (그러나 사용하기 전에). 정적 생성자가있는 경우 정적 생성자의 코드가 필드를 초기화 할 수 있습니다. 즉, 유형을 요청할 때 런타임에서 필드를 초기화 할 수만 있습니다.

따라서 필드를 사용하기 전에 런타임에서 필드를 '사전 예방 적으로'초기화하지 않으려면 정적 생성자를 추가하십시오.

어느 쪽이든, 싱글 톤을 구현하는 경우 런타임에서 변수를 초기화해야한다고 생각하지 않을 때 가능한 한 게으른 초기화를 원하거나 신경 쓰지 않아도됩니다. 귀하의 질문에서 가능한 한 늦게 원한다고 가정합니다.

그것은 singleton 에 관한 Jon의 게시물을 만났습니다 .이 질문의 기본 주제는 IMO입니다. 아 그리고 의심 :-)

그가 '잘못된'으로 표시된 그의 싱글 톤 # 3이 실제로 정확하다는 것을 지적하고 싶습니다 (잠금은 자동으로 종료시 메모리 장벽을 암시 하기 때문에 ). 또한 인스턴스를 두 번 이상 사용할 때 싱글 톤 # 2보다 빠릅니다 (싱글 톤 :-)). 따라서 게으른 싱글 톤 구현이 실제로 필요한 경우 아마도 그 이유 중 하나 일 것입니다. 간단한 이유 때문에 (1) 진행중인 코드를 읽는 모든 사람에게 매우 분명합니다. 예외적으로.

궁금한 점이있는 경우 : 싱글 톤 # 6을 사용하지 않는 경우가 있습니다. 예외적으로 교착 상태와 예기치 않은 동작이 발생할 수 있기 때문입니다. 자세한 내용은 lazy의 잠금 모드 , 특히 ExecutionAndPublication을 참조하십시오 .


62
Regarding question (1): The answer from Jon is correct ...존 스키트는 항상 정확합니다 ....
Noctis

72
Jon Skeet이 이미 답변 한 Jon Skeet 질문에 대한 답변을 시도하기위한 추가 포인트.
valdetero

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