[c#] 읽기 전용 속성을 구현하는 방법

내 유형에 읽기 전용 속성 을 구현해야 합니다. 또한이 속성의 값은 생성자에서 설정되며 변경되지 않습니다 (WPF에 대한 사용자 지정 라우팅 UI 명령을 노출하는 클래스를 작성하고 있지만 중요하지 않습니다).

두 가지 방법이 있습니다.

  1. class MyClass
    {
        public readonly object MyProperty = new object();
    }
    
  2. class MyClass
    {
        private readonly object my_property = new object();
        public object MyProperty { get { return my_property; } }
    }
    

이 모든 FxCop 오류가 퍼블릭 멤버 변수를 가져서는 안된다는 오류와 함께 두 번째가 올바른 방법 인 것 같습니다. 옳은?

이 경우 가져 오기 전용 속성과 읽기 전용 멤버간에 차이점이 있습니까?

나는 어떤 의견 / 조언 / 등을 감사 할 것입니다.



답변

버전 관리 :
소스 호환성에만 관심이 있다면 큰 차이가 없다고 생각합니다.
속성을 사용하면 라이브러리에 따라 컴파일 된 코드를 손상시키지 않고 setter가있는 속성으로 대체 할 수 있으므로 바이너리 호환성에 더 좋습니다.

대회 : 대회
를 따르고 있습니다. 이와 같은 경우 두 가능성의 차이가 관례에 따라 비교적 사소한 경우가 더 좋습니다. 다시 물릴 수있는 한 가지 경우는 반사 기반 코드입니다. 속성 편집기 / 뷰어와 같이 필드가 아닌 속성 만 허용 할 수 있습니다.

Serialization
필드에서 속성으로 변경하면 많은 serializer가 손상 될 수 있습니다. 그리고 AFAIK XmlSerializer는 공용 필드가 아닌 공용 속성 만 직렬화합니다.

Autoproperty 사용
또 다른 일반적인 변형은 private setter와 함께 autoproperty를 사용하는 것 입니다. 짧고 속성이지만 읽기 전용을 적용하지 않습니다. 그래서 나는 다른 것을 선호합니다.

읽기 전용 필드는 자체 문서화
입니다. 그러나 필드의 한 가지 장점이 있습니다
. 공개 인터페이스에서 실제로 변경 불가능하다는 것을 한 눈에 분명히 보여줍니다 (반사를 제외하고). 부동산의 경우에만 볼 수 있습니다. 당신이 문서 또는 구현을 참조해야 할 것이다, 그래서 그것을 변경할 수 없습니다.

그러나 솔직히 나는 게으 르기 때문에 응용 프로그램 코드에서 첫 번째 것을 자주 사용합니다. 도서관에서는 일반적으로 더 철저하고 규칙을 따릅니다.

C # 6.0은 읽기 전용 자동 속성을 추가합니다.

public object MyProperty { get; }

따라서 이전 컴파일러를 지원할 필요가 없을 때 읽기 전용 필드만큼 간결한 코드로 진정한 읽기 전용 속성을 가질 수 있습니다.


답변

두 번째 방법은 선호하는 옵션입니다.

private readonly int MyVal = 5;

public int MyProp { get { return MyVal;}  }

이렇게하면 MyVal초기화시에만 할당 할 수 있습니다 (생성자에서도 설정할 수 있음).

언급했듯이-이렇게하면 내부 구성원을 노출하지 않으므로 나중에 내부 구현을 변경할 수 있습니다.


답변

C # 6 (VS 2015)의 도입으로 이제 get암시 적 지원 필드가있는 자동 속성 만 가질 readonly수 있습니다 (즉, 값은 생성자에서 할당 할 수 있지만 다른 곳에서는 할당 할 수 없음).

public string Name { get; }

public Customer(string name)  // Constructor
{
    Name = name;
}

private void SomeFunction()
{
    Name = "Something Else";  // Compile-time error
}

이제 속성 (setter 포함 또는 제외)을 인라인으로 초기화 할 수도 있습니다.

public string Name { get; } = "Boris";

질문을 다시 살펴보면 옵션 1의 간결함과 함께 옵션 2 (공개 구성원은 필드가 아니라 속성 임)의 장점을 제공합니다.

불행히도 클래스의 소비자에게 setter가없는 것은 private setter가있는 것과 구별 할 수 없기 때문에 공용 인터페이스 수준 (@CodesInChaos의자가 문서화에 대한 요점에서와 같이) 수준에서 불변성을 보장하지 않습니다.


답변

다음과 같이 할 수 있습니다.

public int Property { get { ... } private set { ... } }


답변

두 번째 방법이 더 바람직하다는 데 동의합니다. 이 기본 설정에 대한 유일한 실제 이유는 .NET 클래스에 공용 필드가 없다는 일반적인 기본 설정 때문입니다. 그러나 해당 필드가 읽기 전용이면 다른 속성과의 일관성 부족 외에 실제 이의가있는 것을 알 수 없습니다. 읽기 전용 필드와 가져 오기 전용 속성의 실제 차이점은 읽기 전용 필드는 해당 값이 개체의 수명 동안 변경되지 않고 가져 오기 전용 속성이 변경되지 않음을 보장한다는 것입니다.


답변

두 번째 방법은 캡슐화 때문에 선호됩니다. 읽기 전용 필드를 공개 할 수는 있지만 데이터 액세스 권한이있는 C # 관용구는 필드가 아니라 속성을 통해 발생합니다.

그 이유는 속성이 공용 인터페이스를 정의하고 해당 속성에 대한 지원 구현이 변경 되어도 구현이 인터페이스 뒤에 숨겨져 있기 때문에 코드의 나머지 부분을 깨뜨리지 않기 때문입니다.


답변

또 다른 방법 (내가 가장 좋아하는), C # 6부터

private readonly int MyVal = 5;

public int MyProp => MyVal;

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties#expression-body-definitions