2009-06-26 4 views
3

편집 : David's 대답을 수락했지만 Jon's 응답도 고려해야합니다.get 메소드의 값을 설정하는 기본 메소드 : 생성자와 백업 필드

읽기 전용 (get only?) 속성의 값을 설정할 때 선호되는 방법은 무엇입니까? 배킹 필드를 사용하거나 생성자를 사용합니까? 디자인이 필드가 아닌 속성에 대한 것으로 가정합니다 (나중에 필드를 사용하지 못하게하는 설정자가 속성에 있어야하는 업데이트가있을 수 있음).

다음과 같은 간단한 예가 주어지면 어떤 방법이 선호됩니까? 하나가 다른 것보다 선호된다면, 왜?

옵션 1 (배면 필드) :

class SomeObject 
{ 
    // logic 
} 

class Foo 
{ 
    private SomeObject _myObject; 
    public SomeObject MyObject 
    { 
     get 
     { 
      if(_myObject == null) 
      { 
       _myObject = new SomeObject(); 
      } 
      return _myObject; 
     } 
    } 

    public Foo() 
    { 
     // logic 
    } 
} 

옵션 2 (생성자) :

그것은 필요로하는 시간에 따라
class SomeObject 
{ 
    // logic 
} 

class Foo 
{ 
    public SomeObject MyObject { get; private set; } 

    public Foo() 
    { 
     MyObject = new SomeObject(); 
     // logic 
    } 
} 

답변

7

"새로운 SomeObject의();" getter가 전혀 호출되지 않을 가능성이 있습니다.

MyObject를 만드는 데 많은 비용이 들고 Foo() 인스턴스를 만들 때마다 사용하지 않으면 옵션 1을 사용하는 것이 좋습니다.이 방법을 게으른 초기화라고합니다. Chrome과 같은 프로그램은 시작 시간을 줄이기 위해 많이 사용합니다. 당신은 어쨌든 MyObject를 매번 만들려고하고 게터 매우 자주 호출되는 경우

, 당신은 2

+0

게으른 초기화에 대한 좋은 점. –

0

개인적으로 옵션을 각각의 액세스에 대한 비교를 절약 할 수 있습니다 내가 처음 있지만, 이동을 할 것 생성자에 대한 초기화.

class Foo 
{ 
    private SomeObject myObject; 

    public SomeObject MyObject 
    { 
     get { return myObject; } 
    } 

    public Foo() 
    { 
     myObject = new SomeObject(); 
    } 
} 

왜? 나는 개인적으로 private set을 사용하지 않는다. 그 이유는 어떤 프로퍼티가 어떤 프로퍼티를 가지고 있는지를 기억해야하고 어떤 프로퍼티는 클래스 코드 전체에서 소문자와 대문자를 사용한다는 것을 의미한다. 그 사소한 "불일치"는 내 자기 강박증을 괴롭힌다.

비록 사소한 스타일 선호도입니다. 하나는 여섯, 다른 하나는 여섯 개. 옵션 # 2에 대해서는 아무 것도 없습니다. private set 관용구에 반대하지 마십시오.

+0

정확히 이것의 이점은 무엇입니까? 항상 myObject를 초기화 (지연로드를 잃어 버림)하고 명백한 이유없이 자동 소품을 피합니다. –

+1

나는 게으른 초기화 측면이 질문의 주된 추진력이 아니라고 생각했다. 그게 중요하다면 2 번 옵션을 사용하지 않을 것입니다. –

+0

@ 존 - 질문의 핵심은 게으른 초기화에 관한 것이 아니라는 점입니다. 오히려, 선호되는 방법은 무엇입니까 ... 다른 하나를 사용할 때와 그 반대의 경우. –

2

것은 요즘이 방법을 아주 좋아했습니다

class Foo 
{ 
    public SomeObject MyObject { get; private set; } 

    public Foo() 
    { 
     MyObject = new SomeObject(); 
    } 
} 
+0

최근에 그 일을 너무 많이하고 있습니다. –

+0

내부에서도 만들 수 있습니다. – eschneider

5

많은 경우에 나는 종류는 불변 할 것을 좋아합니다. 가능하다면 나는 을 적절하게으로 변경하고 싶습니다. 이는 자동으로 구현 된 속성을 완전히 피하는 것을 의미합니다. 그렇지 않으면 유형이 여전히 동일한 클래스 내에서 변경 가능하며 버그가 발생하기를 기다리고 있습니다.

"올바른"불변성은 보조 필드를 읽기 전용으로 만드는 것입니다. 즉, 은 생성자에서 설정하기 위해을 가지고 있습니다. 일반적으로 다른 매개 변수에서 초기화합니다. 나는 당신이 당신의 질문에서와 같이 더 이상 정보없이 인스턴스를 게으르게 생성 할 수 있다는 것이 매우 드뭅니다.- 성가신 얻을 수있는 하나의 생성자에 그들 모두를 통과하면 특성을 많이 가지고 때

public class Person 
{ 
    private readonly string name; 
    public string Name { get { return name; } } 

    public Person(string name) 
    { 
     this.name = name; 
    } 
} 

이 다루기가된다 : 즉,이 나를 위해 일반적인 패턴이다. 여기서 초기화 데이터를 수집하는 데 사용할 수있는 변경 가능한 유형의 빌더 패턴을 사용하고 빌더 만 사용하는 생성자를 사용하려고합니다. 또는 C# 4에서 사용할 수있는 명명 된 인수와 선택적 매개 변수를 사용하면이 작업을 약간 더 쉽게 수행 할 수 있습니다.

다시 정확한 상황을 얻으려면, 나는 보통 쓰는 것 :

SomeObject을 구성하는 것은 특히 비싼하지 않는 것입니다
class Foo 
{ 
    private readonly MyObject myObject; 
    public SomeObject MyObject { get { return myObject; } } 

    public Foo() 
    { 
     myObject = new MyObject(); 
     // logic 
    } 
} 

. 속성에서 지연적으로 수행하는 것보다 잠재적으로 스레드 문제에 대해 걱정할 필요가없는 것보다 간단합니다.

지금 나는 불변성이 여기 유용한 목표라고 가정했습니다.하지만 당신은 세터를 추가하는 것에 대해 이야기 해 왔습니다. 필드를 사용하는 것이 왜 불가능하다고 생각하는지 모르겠지만 확실히 그렇지는 않습니다. 예를 들어, 코드의 첫 번째 조각에서 게으른 인스턴스를 결합 할 수 있으며,이 같은 세터 갖는

class Foo 
{ 
    private SomeObject _myObject; 
    public SomeObject MyObject 
    { 
     get 
     { 
      if(_myObject == null) 
      { 
       _myObject = new SomeObject(); 
      } 
      return _myObject; 
     } 
     set 
     { 
      // Do you want to only replace it if 
      // value is non-null? Or if _myObject is null? 
      // Whatever logic you want would go here 
      _myObject = value; 
     } 
    } 

    public Foo() 
    { 
     // logic 
    } 
} 

을 나는 중요한 결정을해야한다고 생각 :

  • 당신이 할 유형을 원하십니까 제대로 불변?
  • 지연 초기화가 필요합니까?
  • 속성에 다른 로직이 필요합니까?

이들 모두에 대한 대답이 아니오 인 경우 자동으로 구현 된 속성을 사용하십시오. 세 번째 대답이 yes로 변경되면 나중에 자동으로 구현 된 속성을 "일반"속성으로 변환 할 수 있습니다.

관련 문제