개인 변수 대 속성?


41

대부분 클래스 내에서 변수로 값을 설정하면 두 가지 옵션이 제공됩니다.

private string myValue;
public string MyValue
{
   get { return myValue; }
   set { myValue = value; }
}

클래스 내부의 변수에 값을 할당하는 방법을 결정하는 규칙이 있습니까? 예를 들어 같은 클래스 내에 메서드가있는 경우 속성이나 개인 변수를 사용하여 메서드를 할당해야합니다. 나는 그것이 두 가지 방법으로 수행되는 것을 보았으므로 이것이 선택인지 또는 성능이 중요한지 궁금해했다.

답변:


23

한 걸음 더 나아가서 3 가지 사례를 가져 왔습니다. 각각에 변형이 있지만 이것은 C # 프로그래밍시 대부분의 시간을 사용하는 규칙입니다.

2 & 3의 경우 항상 필드 접근자가 아닌 속성 접근 자로 이동하십시오. 그리고 1 번의 경우에, 당신은이 선택을해야 할 필요가 없습니다.

1.) 불변 속성 (생성자에게 전달되거나 생성시 생성됨). 이 경우 읽기 전용 속성과 함께 필드 변수를 사용합니다. 개인 세터가 불변성을 보장하지 않기 때문에 개인 세터보다 이것을 선택합니다.

public class Abc
{ 
  private readonly int foo;

  public Abc(int fooToUse){
    foo = fooToUse;
  }

  public int Foo { get{ return foo; } }
}

2.) POCO 변수. 모든 공개 / 개인 범위에서 가져 오거나 설정할 수있는 간단한 변수입니다. 이 경우 자동 속성을 사용합니다.

public class Abc
{ 
  public int Foo {get; set;}
}

3.) ViewModel 바인딩 속성. INotifyPropertyChanged를 지원하는 클래스의 경우 개인 지원 필드 변수가 필요하다고 생각합니다.

public class Abc : INotifyPropertyChanged
{
  private int foo;

  public int Foo
  {
    get { return foo; }
    set { foo = value;  OnPropertyChanged("foo"); }
  }
}

2
MVVM 예제의 경우 +1 실제로 그것은 처음에 질문을 일으켰습니다.
Edward

4
+1 : 2/3와 AOP를 혼합하면 INPC를 훌륭하게 사용할 수 있습니다. [알림] public int Foo {get; 세트; }
Steven Evers

1
@Job 클래스에 액세스하는 모든 클래스에는 개인 설정자가 불변성에 충분합니다. 그러나 클래스 내부에서 개인 설정 기는 초기 구성 후에 값의 반복 설정을 막지 않습니다. 'private readonly set'과 같은 언어 기능은 개념적으로이 문제를 해결할 수 있지만 존재하지는 않습니다.
쉘던 Warkentin

1
나는 C #을 처음 사용 하므로 public int Foo {get; set;} 대신 사용 public int Foo합니까?

1
클래스 또는 구조체가 POCO 또는 PODS로 동작 할 경우 필드를 속성에 래핑하면 어떤 실질적 이점이 있습니까? 속성에 필드를 줄 바꿈하는 것은 클래스 또는 구조체가 내용과 관련하여 불변을 유지해야 할 때 (나중에 필요할 때 또는 다른 객체가 일치하도록 업데이트해야 함) 유용하지만 클래스 또는 구조체 인 경우 유용하다는 것을 완전히 이해합니다 소비자가 제한이나 부작용없이 어떤 순서로든 값을 쓸 수 있음을 명시합니다. 멤버 접근 자에게 어떤 유용한 동작을 추가 할 수 있습니까?
supercat

18

일반적으로 생성자의 필드에 할당하고 다른 곳에서 속성을 사용한다고 말합니다. 이런 식으로 누군가가 속성에 기능을 추가하면 놓칠 수 없습니다.

확실히 성능 요소는 아닙니다. 옵티마이 저는 간단한 get 또는 set을 인라인하고 최종 MSIL 코드는 동일 할 것입니다.


생성자에서 필드를 사용하는 특별한 이유가 있습니까? 이상한 부작용의 가능성이 적습니까?
Sign

4
@Sign : 내 생각에 부동산에 대한 유효성 검사가 있거나 (현재 또는 미래에) 건설 중에 유효성 검사가 실패 할 위험이 있다고 생각하지 않습니다. 이 단계에서는 생성자가 완료 될 때까지 개체가 안정적으로 보장 될 수 없으므로 유효성 검사는 논리적이지 않습니다.
Steven Evers 2019

@Sign : 당신의 말과 Snorfus의 말. 또는 속성에 대한 변경 사항을 기록하려면 초기 설정을 기록하고 싶지 않을 수 있습니다. 그러나 나는 "일반적으로"라고 말했습니다.
pdr

3
@Sign : 문제는 : 서브 클래스에서 프로퍼티의 set 메소드를 오버라이드 할 수있는 경우, 오브젝트 또는 불일치 한 오브젝트를 생성하는 동안 부작용이 발생할 수 있습니다 (예 : 오버라이드 된 프로퍼티는 값을 설정하지 않도록 프로그래밍 됨) 그 분야). 생성자에서 속성을 사용하는 것은 set 메소드가 private이거나 클래스가 봉인 된 경우에만 안전합니다.
Diego

4

다릅니다.

먼저 가능한 경우 자동 속성을 선호해야합니다.

public string MyValue {get;set;}

둘째, 더 좋은 방법은 속성을 사용하는 것입니다. 논리가있는 경우 특히 논리가 스레드 동기화 인 경우 직접 전달해야합니다.

그러나 동기화가 제대로 수행되지 않으면 성능이 약간 저하 될 수 있음을 고려해야합니다.


3
나도 좋아 public string MyValue {get; private set;}.
직업

3

클래스 간 메서드 안에 있고 어쨌든 클래스의 동작을 제어하기 때문에 직접 접근 방식은 변수 자체에 변수를 할당하는 것입니다.

그러나 속성에 대한 요점은 변수를 추상화하는 것입니다. 예제와 같은 간단한 속성은 단순한 공용 멤버 변수를 완전히 사용하지 않지만 속성은 일반적으로 게터와 세터 내부에서 추가 작업을 수행합니다 (또는 수행해야합니다). 그리고 클래스 내에서 속성을 변경할 때 이러한 작업을 자동으로 수행하려면 속성 설정 동작이 변경 될 때 각 변수 할당을 변경하지 않아도되도록 변수 대신 속성에서 작업하는 것이 더 깨끗합니다.

개념적으로 추론해야합니다. 이 속성은 실제로 개체의 내부 상태에 액세스하기위한 핸들이며, 둘 이상의 멤버 변수로 구성 될 수 있습니다. 따라서 기본 내부 상태 만 (또는 그 일부만) 또는이 상태를 나타내는 추상 속성을 변경하고 싶은지 스스로에게 물어봐야합니다. 대부분은 일반적으로 객체가 항상 원하기 때문에 후자입니다. 일관된 상태.


2

해당 속성 get / set 구현이 나중에 나중에 변경 될 가능성이있는 경우 (예 :를 호출 할 때 이벤트를 발생 set시키거나 나중에 get함수에 게으른 평가 메커니즘을 추가 하려는 경우 ) 좋은 아이디어 일 수 있습니다. 클래스 내부의 코드는 명시 적으로 이벤트 또는 지연 평가 메커니즘을 사용 하지 않으려 경우를 제외하고 거의 모든 경우에 속성을 사용합니다.

어쨌든, 당신이 무엇을하든 나중에 나중에 그런 식으로 속성 구현을 변경하면 해당 속성에 액세스하는 클래스 내부의 모든 위치를 살펴보고 실제로 속성에 액세스하는지 또는 전용 변수를 사용해야합니다.


2

나는 항상 공공 재산을 사용합니다.

속성이 설정 될 때 항상 실행되어야하는 일부 논리가 속성의 set메서드에 추가되고 개인 필드를 설정하는 대신 공용 설정자가 해당 논리를 무시합니다.

이 질문으로 이어지는 MVVM에 대한 의견이 있으며 MVVM을 사용할 때 이것이 더 중요하다고 생각합니다. 많은 객체 PropertyChange가 setter에 대한 알림을 발생시키고 다른 객체는 특정 속성이 변경 될 때 일부 이벤트를 실행하기 위해이 이벤트에 가입 할 수 있습니다. 개인 변수를 설정하면 PropertyChanged이벤트를 수동으로 발생시키지 않으면 이러한 작업이 실행되지 않습니다 .


+1 예 (MVVM) 대부분의 경우 PropertyChanged 이벤트는 필수입니다. 그리고 그것은 단지 재산 안에서만 해고 될 수 있습니다. 좋은 설명입니다.
Edward

1

일반적으로, 가져 오거나 설정할 때 속성 및 지원 필드로 수행해야 할 작업은 사용자의 몫입니다.

대부분의 경우 코드 전체에서 일관성을 유지하려면 공용 접근자를 사용 가능한 적절한 위치에 사용해야합니다. 최소한의 코드 변경으로 리팩터링 할 수 있습니다. 이 설정을 수행하는 메소드를 클래스에서 제거해야하고 기본 필드와 같이 더 이상 지원 필드를 사용할 수없는 다른 곳에 두어야하는 경우 누가 신경 쓰나요? 수업 자체가 작업을 수행하는 모든 곳에서 사용 가능한 것을 사용하고 있습니다. 대부분의 경우 지원 필드는 구현 세부 사항입니다. 수업 이외의 어느 누구도 그것이 존재한다는 것을 알아야합니다.

속성 필드가 아닌 지원 필드를 사용해야 할 때 내가 생각할 수있는 주요 상황은 접근자가 실행하지 않으려는 추가 논리 (유효성 검사 또는 클래스의 다른 상태 정보 업데이트)가있는 경우입니다. 객체의 초기 모집단이 예입니다. 두 가지 속성 값을 사용하여 세 번째 속성을 계산하는 클래스가있을 수 있습니다.이 속성 값은 지속성 이유로 백업 필드에도 저장됩니다. DB로부터 데이터가 주어진 해당 객체의 새 복사본을 초기화 할 때, 세 번째 값을 각각 다시 계산하는 속성 접근자는 다른 필요한 값이 설정되지 않으면 불만을 표시 할 수 있습니다. 지원 필드를 사용하여이 두 (또는 세) 속성의 초기 값을 설정하면 인스턴스가 논리가 정상적으로 작동 할 수있을만큼 일관된 상태가 될 때까지 유효성 검사 / 계산 논리를 무시합니다.


0

항상 말이되는 것을 사용하십시오. 예, 나는 대답이 없다는 점에서 꽤 가짜처럼 들립니다.

속성의 핵심은 데이터 모델에 안전하게 액세스 할 수있는 인터페이스를 제공하는 것입니다. 대부분의 경우 항상 다음과 같은 인터페이스를 통해 데이터 모델에 안전하게 액세스하려고합니다.

public Foo Bar
{
  get { return _bar; }
  set { _bar = doSomethingTo(value); }
}

그러나 다른 상황에서는 단순히 속성을 데이터 모델의보기로 사용하고있을 수 있습니다.

public Double SomeAngleDegrees
{
  get { return SomeAngleRadians * 180 / PI; }
  set { SomeAngleRadians = value * PI / 180; }
}

라디안 형태의를 사용하는 것이 이치에 맞다면 반드시 사용하십시오 SomeAngle.

결국, 자신의 쿨 에이드를 마셔야합니다. 공개 대면 API는 내부적으로 작업 할 수있을 정도로 탄력적이어야합니다.

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