2011-01-06 5 views
8

현재 값 비싼 초기화를 클래스 생성자에서 지연 초기화 된 (Lazy Initialized) 속성으로 옮기기 위해 널리 사용되는 클래스를 변경하고 있습니다.속성으로 지연 초기화하는 방법

하기 전에 :

public class ClassA 
{ 
    public readonly ClassB B; 

    public void ClassA() 
    { 
     B = new ClassB(); 
    } 
} 

후 :

public class ClassA 
{ 
    private ClassB _b; 

    public ClassB B 
    { 
     get 
     { 
      if (_b == null) 
      { 
       _b = new ClassB(); 
      } 

      return _b; 
     } 
    } 
} 

가 나는 변화하고있어 클래스에서 이러한 속성의 공정한 몇 가지 더, 일부 아래 (C#에서) 예입니다 어떤 맥락에서는 사용되지 않지만 (따라서 게으름), 사용된다면 반복적으로 호출 될 가능성이 있습니다.

불행히도 속성은 종종 클래스 내부에서도 사용됩니다. 즉, 개인 변수 (_b)가 초기화되지 않은 메소드에서 직접 사용될 가능성이 있음을 의미합니다.

클래스 내에서 공용 속성 (B) 만 사용할 수있는 방법이 있습니까? 아니면 필요에 따라 초기화 된 대체 방법을 사용할 수 있습니까?

이것은 (안 주관적만큼 분명히) 프로그래머에서 다시 게시 : https://softwareengineering.stackexchange.com/questions/34270/best-methods-for-lazy-initialization-with-properties

+0

@chibacity : 감사합니다. –

답변

6

지연 변수에 대한 직접 액세스를 피하기 위해 지연 클래스를 기본 클래스로 푸시하는 것이 좋습니다. 내가 알지 못하는 이상. 저는 항상 이것이 C#에서 부족한 것으로 생각했습니다. 즉, 게으른 속성을 직접 지원합니다.

+0

.Value를 참조하지 않고도이 모든 필요성을 제거하고 암시 적으로 느린 로딩 된 속성을 갖도록 게으른 속성을 지정할 수 있다면 좋을 것입니다. – BenAlabaster

+0

@BenAlabaster 처음 자동 속성을 보았을 때 나는 게으른 기능을 추가했다고 생각했습니다. 초기화 함수 func을 사용하여 자동 속성을 정의 할 수 있다면 좋을 것입니다. –

+0

@chibacity 흥미로운 생각, 그게 성취 할 수 있을지 궁금하다 ... 놀기 시작하는 시간;) – BenAlabaster

16

글쎄, 내 권장 솔루션은 재산이 아니라 필드를 사용하도록 동료에게하는 것입니다. 하지만 다음과 같이 어느 정도 바보 증명을 할 수 있습니다.

public class ClassA 
{ 
    private Lazy<ClassB> _b = new Lazy<ClassB>(() => new ClassB()); 

    public ClassB B 
    { 
     get 
     { 
      return _b.Value; 
     } 
    } 
} 

이제는 망쳐 버리는 것이 꽤 어렵습니다.

+0

+1. 이것은 제가 제안하려고했던 것입니다. –

+0

이 예에서'Lazy '은 정확히 무엇입니까? 감사. –

+0

니스, 나는 게으름 뱅이 클래스에 대해 몰랐습니다; 그러나 그것은 OP에서 무엇을 사용하고 있는지 확실하지 않은 4 번째 새로운 것으로 보인다. –

3

@chibacity는 추상 기본 클래스를 사용하는 대체 옵션 ([삭제 후 삭제 취소됨 : P])을 대체 옵션으로 게시합니다. 그것은 코드 배포면에서 이상적이지는 않지만 더 깨끗하고 간결한 ClassA를 만들기 위해 많은 코드 혼란을 제거하는 멋진 캡슐화를 제공합니다. 이 더 긴 호흡처럼 보인다, 언뜻

public class ClassB { /* Class to be lazily instantiated */ } 

public abstract class BaseA 
{ 
    private Lazy<ClassB> _b = new Lazy<ClassB>(() => new ClassB()); 
    public virtual ClassB B { get { return _b.Value; } } 
} 

public class ClassA : BaseA 
{ 
    public override ClassB B { get { return base.B; } } 
} 

하지만를 ClassA 것을 고려할 때 당신이 일하게 될 것이다 클래스는 어느 : 예를 들어, 당신은 둘 다 목표를 달성하기 위해 기술을 결합 고려할 수 이 말은 이제 모든 참조가 동일한 속성을 통과한다는 것을 의미합니다. 잠재적 인 혼란을 야기하는 불필요한 불필요한 필드가 없으며 직접 _b를 참조하는 속성을 우회 할 필요가 없으며 동료에게 사용할 곳을 말할 필요가 없습니다. 오직 하나.

이렇게하는 것이 올바른 방법인지 또는 따라야하는 패턴인지는 모르겠지만 @chibacity가 제안한 장점을 지적하고 있습니다.

B.Value를 참조하지 않고도 암시 적으로 지연 등록 정보를 가질 수 있다면 좋을 것입니다 ...예를 들면 : 매개 변수가없는 생성자가없는

[Lazy] 
public ClassB B { get; } 

나에 대한 객체

[Lazy(() => new ClassB("Hello", "World"))] 
public ClassB B { get; } 

혹은 @chibacity 코멘트

public ClassB B { lazyget; } 

또는

public ClassB B { lazyget : new ClassB(); } 

아아에 제안, I 아무도 생각하지 마라. se는 현재 어떤 형태로든 사용할 수있는 솔루션입니다 ...

+0

func 및 특성을 사용하는 구문을 좋아하지만 불행히도 특성 인수는 컴파일 타임 상수 여야합니다. :) –

+0

@chibacity API를 작성할 때 항상 의식하고있는 것 중 하나입니다.이 함수를 호출하거나이 기능을 사용할 때 구문을 표시하려면 어떻게해야합니까? 보통 모든 것을 그렇게 할 수 있도록 내 API를 디자인하기 전에 내 호출을 원하는대로 디자인합니다. – BenAlabaster

관련 문제