[c#] 개인 세터 이해

C # 2로 시작된 개인 setter가 필요하다는 것을 이해하지 못합니다.

나를 위해 setter 메서드를 사용하면 사용자가 해당 클래스에서 일부 변수를 설정할 수 있습니다. 그렇게 할 때 변수를 사용자에게 직접 노출하지 않습니다. 대신에 우리는이 공용 setter 메서드를 통해이를 수행하도록합니다.

이것은 나를 위해 “캡슐화”를 사용하고 있습니다. private setter가 캡슐화를 적용 할 수 있다고 주장하는 몇 가지 주장이 있습니다.

공용 setter 메서드를 사용하여 캡슐화를 사용하지 않습니까? 개인 세터가 필요한 이유는 무엇입니까?

불변 클래스와 private setter가있는 클래스의 차이점은 무엇입니까?



답변

논리적으로.

private setter의 존재는 auto 속성을 사용할 수 있기 때문입니다.

public int MyProperty { get; set; }

읽기 전용으로 만들고 싶다면 어떻게 하시겠습니까?

public int MyProperty { get; }

젠장!! 내 수업에서 액세스 할 수 없습니다. 일반 속성처럼 만들어야합니다.

private int myProperty;
public int MyProperty { get { return myProperty; } }

흠 …하지만 “자동 속성”기능이 없어졌습니다 …

public int MyProperty { get; private set; }

AHHH .. 그게 낫다 !!


답변

private setter는 읽기 전용 속성이 있고 백업 변수를 명시 적으로 선언하지 않으려는 경우 유용합니다.

그래서:

public int MyProperty
{
    get; private set;
}

와 같다:

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}

자동 구현되지 않은 속성의 경우 클래스 에서 속성을 설정하는 일관된 방법을 제공 하므로 유효성 검사 등이 필요한 경우 한 곳만 사용할 수 있습니다.

최종 질문에 답하기 위해 MSDN은 개인 세터에 대해 다음과 같이 말합니다.

그러나 값 집합 (데이터) 만 캡슐화하고 동작이 거의 또는 전혀없는 작은 클래스 또는 구조체의 경우 set 접근자를 private으로 선언하여 개체를 변경 불가능하게 만드는 것이 좋습니다.

에서 자동 구현 속성에 대한 MSDN 페이지


답변

다소 간단합니다. Private setter를 사용하면 읽기 전용 공용 또는 보호 된 속성을 만들 수 있습니다.

그게 다야. 그게 유일한 이유입니다.

예, getter 만 지정하여 읽기 전용 속성을 만들 수 있지만 자동 구현 속성을 사용하면 get과 set을 모두 지정해야하므로 자동 구현 속성을 읽기 전용으로 지정하려면 다음을 사용해야 합니다. 개인 세터. 다른 방법은 없습니다.

Private setter가 자동 구현 된 읽기 전용 속성을 위해 특별히 생성되지는 않았지만, 그 사용은 주로 읽기 전용 속성과 리플렉션 및 직렬화 사용을 중심으로하는 다른 이유로 인해 좀 더 난해합니다.


답변

C # 6.0Auto-Property Initializers 구문 이 도입됨에 따라 인라인 또는 생성자 내에서 초기화시에만 설정되는 속성에 더 이상 전용 setter가 필요하지 않습니다.

이제 다음과 같은 새로운 구문이 컴파일됩니다.

인라인 초기화 속성

public class MyClass1 {
  public string MyProperty { get; } = "Aloha!"
}

생성자 초기화 속성

public class MyClass2 {
  public string MyProperty { get; }

  public MyClass2(string myProperty) {
    MyProperty = myProperty;
  }
}


답변

C # 2로 시작된 개인 setter가 필요하다는 것을 이해하지 못합니다.

예를 들어, 송장 클래스는 사용자가 Items 속성에서 항목을 추가하거나 제거 할 수 있도록 허용하지만 사용자가 Items 참조를 변경하는 것을 허용하지 않습니다 (즉, 사용자가 Items 속성을 다른 항목 목록 개체 인스턴스에 할당 할 수 없음).


public class Item
{
  public string item_code;
  public int qty;

  public Item(string i, int q)
  {
    this.item_code = i;
    this.qty = q;
  }
}

public class Invoice
{
  public List Items { get; private set; }

  public Invoice()
  {
    this.Items = new List();
  }
}

public class TestInvoice
{
  public void Test()
  {
    Invoice inv = new Invoice();
    inv.Items.Add(new Item("apple", 10));

    List my_items = new List();
    my_items.Add(new Item("apple", 10));

    inv.Items = my_items;   // compilation error here.
  }
}


답변

예를 들어 속성을 통해 실제 변수를 저장하지 않거나 값을 사용하여 무언가를 계산하지 않습니다.

이 경우 계산을 수행하는 방법을 만들 수 있습니다.

private void Calculate(int value)
{
 //...
}

또는 다음을 사용하여 수행 할 수 있습니다.

public int MyProperty {get; private set;}

이 경우 속성이 각 멤버 요소를 그대로 리팩토링하므로 나중에 사용하는 것이 좋습니다.

그 외에는 변수로 속성을 매핑한다고해도 말입니다. 이 경우 코드 내에서 다음과 같이 작성하고 싶습니다.

public int myprop;
public int MyProperty {get { return myprop;}}

... ...

this.myprop = 30;

... ...
if(this.MyProperty > 5)
   this.myprop = 40;

프로그래머가 Get에 MyProperty를 사용하고 Set에 대해 myprop를 사용하는 데 항상주의해야하기 때문에 위의 코드는 끔찍해 보입니다.

일관성을 위해 Rether는 Propoerty를 외부에서 읽기 전용으로 만드는 Private setter를 사용할 수 있으며 코드 내부에서 setter를 사용할 수 있습니다.


답변

나는 몇몇 사람들이 이것에 대해 춤을 추 었다고 생각하지만, 나에게 private setter의 가치는 심지어 클래스 내에서도 속성의 동작을 캡슐화 할 수 있다는 것입니다. abhishek이 언급했듯이 속성이 변경 될 때마다 속성 변경 이벤트를 발생시키고 싶지만 속성이 공개적으로 읽기 / 쓰기되는 것을 원하지 않는 경우 개인 설정기를 사용하거나 백업 필드를 수정하는 모든 위치에서 이벤트. 후자는 잊어 버릴 수 있기 때문에 오류가 발생하기 쉽습니다. 이와 관련하여 속성 값을 업데이트하면 일부 계산이 수행되거나 다른 필드가 수정되거나 무언가의 지연 초기화가 발생하는 경우 모든 곳에서 수행하는 것을 기억할 필요없이 개인 setter로 래핑하는 것이 좋습니다. 지원 필드의 사용.