개인 필드가 있거나없는 속성을 선호해야합니까?


16

현재 작업중 인 코드베이스에는 개인 필드 및 공용 속성을 사용하는 규칙이 있습니다. 예를 들어, 대부분의 클래스에는 다음과 같이 멤버가 정의되어 있습니다.

// Fields
private double _foo;
private double _bar;
private double _baz;

// Properties
public double Foo
{
    get{ return _foo; }
    set{ _foo = value; }
}

public double Bar
{
    get{ return _bar; }
    set{ _bar = value; }
}

public double Baz
{
    get{ return _baz; }
}

내부 개인 속성 없이 이러한 속성을 다시 작성할 수 있다는 것을 알고 있습니다.

public double Foo{ get; set; }
public double Bar{ get; set; }
public double Baz{ get; private set; }

이것에 대한 입력을 원합니다.

  • 더 새롭고 간결한 스타일보다 더 오래되고 더 명시적인 스타일을 선호 할만한 이유가 있습니까?
  • 간결한 스타일을 사용하여 새 클래스를 작성해야합니까, 일관성을 위해 이전 코드와 일치시켜야합니까? 이 경우 일관성이 이전 형식을 정당화하기에 충분합니까?

질문과 답변을 참조하십시오 .
Peter K.

@PeterK. 유익한. 나머지 프로그램의 스타일을 유지하는 것에 대해 걱정 해야하는지 여부 또는 중요하지 않은 작은 세부 사항인지는 대답하지 않습니다.
KChaloux

@KChaloux : 이해했습니다! 그렇기 때문에 답이 아닌 설명입니다. :-)
Peter K.

@PeterK. Fair 'nuff = p
KChaloux

1
변경하지 않는 또 다른 이유는 WCF를 사용하여 와이어를 통해 전달되는 항목이있는 경우입니다. 자동 속성에 .NET에 의해 생성 된 백업 필드 이름의 잘못된 문자로 인해 계약 문제가있는 경우
Leon

답변:


16

소위 "이전"스타일이 여전히 필요한 경우가 몇 가지 있습니다.

A : 언어 제공 불변성을 사용하는 불변 유형. readonlyC # 의 수정자는 생성 후 해당 값을 고정시킵니다. 자동 구현 속성 (아직)으로이를 모방 할 방법은 없습니다.

public sealed class FooBarBazInator
{
    private readonly double foo;

    public FooBarBazInator(double foo)
    {
        this.foo = foo;
    }

    public double Foo
    {
        get
        {
            return this.foo;
        }
    }
}

B : 게터 / 세터는 어떤 논리도 가지고 있습니다. 클래스에 데이터 바인딩 된 WPF 및 Silverlight (및 유사한) 코드는 다음 INotifyPropertyChanged과 같이 구현됩니다 .

public class FooBarBazInator : INotifyPropertyChanged
{
    private double foo;

    public event PropertyChangedEventHandler PropertyChanged;

    public double Foo
    {
        get
        {
            return this.foo;
        }

        set
        {
            this.foo = value;
            this.RaisePropertyChanged("Foo");
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        var propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

그 외에는 새로운 스타일을 사용한다고 말하고 싶습니다. 코드를 간결하게 유지하고 버그가 발생할 수있는 노출 영역을 줄입니다. 또한 로직을 포함하도록 변경해야하는 경우 서명이 호환되지 않습니다.


2
모든 사람들이 새로운 스타일로가는 것에 동의하는 것 같습니다. readonly내가 모르는 수정 자 와 함께 필드의 필요성에 대해 알려 주면 +1과 답을 얻습니다 . = D
KChaloux

3
일부 (나 포함)는 불변의 속성에 대해 개인 접근자가 "충분히 좋은"자동 속성을 고려합니다. 사실, 그들은 불변이 아닐 수도 있지만 생성자 외부에서 setter를 사용하지 않도록주의해야합니다.
svick

2
또 다른 이유는 ref속성에서 작동하지 않는 값을 전달하려는 경우 필드가 필요하다는 것입니다.
stijn

1
Fody와 같은 도구 INotifyPropertyChanged는 명시적인 백업 필드 없이도 구현할 수 있습니다. github.com/Fody/PropertyChanged
Sebastian Redl

3
참고 사항 : C # 6에서는 "예"가 수행하는 작업을 한 줄에 제공하는 "getter-only auto-properties"를 허용합니다.
Jesse C. Slicer

6

명시적인 백업 필드를 갖는 것은 쓸모없는 헛소리라고 말합니다. 코드를 더 길고 읽기 어렵게 만듭니다. 또한 오류 가능성을 추가합니다.

public double Bar
{
    get { return _baz; }
    set { _bar = value; }
}

나는 이런 오류가 아주 쉽게 일어날 수 있고 발견하기가 어렵다고 생각합니다.

일관성을 원한다면 다른 방법으로 수행하십시오. 백업 필드를 사용하는 코드를 자동 속성을 사용하는 코드로 변경하십시오. ReSharper와 같은 리팩토링 도구를 사용하는 경우 특히 쉽습니다 (그렇지 않은 것을 사용하지 않으면 시작해야한다고 생각합니다).

물론, 지원 분야가 필요한 경우가 여전히 있지만이 질문과 관련이 없다고 생각합니다.


실제로 코드를 리팩토링 할 때 몇 가지 오래된 필드 에서이 작업을 수행했습니다 ... 그것은 고통입니다.
KChaloux

1

질문이 꽤 오래되었지만 여기에 언급 할 가치가있는 책에서 읽은 몇 가지 요점을 추가하는 것을 생각했습니다.

  1. 런타임 직렬화 엔진은 직렬화 된 스트림에 파일 이름을 유지합니다. AIP (자동 구현 속성)의 지원 필드 이름은 컴파일러에 의해 결정되며 실제로 코드를 다시 컴파일 할 때마다이 지원 필드의 이름을 변경할 수 있습니다. AIP. 따라서 직렬화 또는 역 직렬화하려는 모든 유형의 AIP를 사용하지 마십시오.

  2. 디버깅 할 때 AIP get 또는 set 메소드에 중단 점을 둘 수 없으므로 애플리케이션이이 특성을 가져 오거나 설정하는시기를 쉽게 감지 할 수 없습니다. 수동으로 구현 된 중단 점에 중단 점을 설정할 수 있습니다


3
# 1-대부분의 시리얼 라이저는 기본적으로 개인 속성 / 필드를 무시합니다. 나는 당신이 언급 한 문제를 겪어 본 적이 없습니다. # 2-이것은 VS2015에서 수정되었으며 VS2013에서 해결할 수 있습니다. 참조 이 비주얼 스튜디오 매거진 기사를 .
Brian

-3

더 새롭고 간결한 스타일보다 더 오래되고 더 명시적인 스타일을 선호 할만한 이유가 있습니까?

실제로는 아닙니다. 비록 당신이 그와 같은 재산을 통과 할 때마다, 당신은 처음에 공공 장소를 사용 했어야한다고 주장 할 것입니다.

간결한 스타일을 사용하여 새 클래스를 작성해야합니까, 일관성을 위해 이전 코드와 일치시켜야합니까? 이 경우 일관성이 이전 형식을 정당화하기에 충분합니까?

위의 조언을 무시하고 통과 속성이 있다고 가정하면 스타일과 일치하는 것을 목표로하지 않습니다. 이상적으로는 이전 스타일을 새로운 스타일로 리팩토링하여 일관성을 유지하지만 사람들이 해당 코드를 잘못 읽을 가능성은 적습니다.



@svick-바. 타입을 반영하지 않으면 차이가 없습니다. 유형을 서비스 또는 라이브러리 인터페이스로 공개적으로 노출하는 경우 어쨌든 속성이 필요한 인터페이스를 노출하게됩니다. OP는 그런 일을하지 않습니다.
Telastyn

2
이러한 제한된 경우 에는 기술적 이유 가 없습니다 . 디버거, 클래스 다이어그램, 인텔리전스에서 속성이 다르게 동작하는 것을 잊지 마십시오. 리플렉션을하지 않는다고 생각할 때 .NET 프레임 워크가 있습니다. WinForms, WPF 및 기타 여러 구성 요소는 내부적으로 리플렉션을 사용하고 속성을 개별적으로 처리하므로 공개 사이트 사용에 대한 조언은이 사이트의 많은 개발자들에게 잘 받아들이지 않을 것입니다.
Kevin McCormick

1
@KevinMcCormick과 프레임 워크는 필드와 완벽하게 잘 작동합니다. 그것은하지 않습니다 정말 문제가 이제 자동 등록이 이후,하지만 더 큰 문제는 처음에 일을 공개하고 있습니다. 지금까지 너무 많은 사람들은 단순히 사물을 만드는 것이 '공공 장을 만들지 말라'는 것을 막는 것이라고 생각합니다.
Telastyn

2
프레임 워크는 다르게 처리합니다 .EF POCO의 공용 필드를 사용하고, DataGridView에 바인딩하고, PropertyGrid를 사용하는 등의 작업을 수행합니다. 디 컴파일러에서 Type.GetProperties / GetProperty를 빠르게 검색하면 프레임 워크 가이 메소드를 호출합니다. 수백 번이지만 GetField에는 없습니다. 결론적으로, 그것들은 다르며, 공개 데이터에 항상 속성을 사용하도록 권장하는 것은이 사실에 부분적으로 기초합니다. 이것은 필드 사용을 배제하지는 않지만 그 경우에는 정당화가 필요합니다. 그러나 공개 데이터를 부주의하게 공개하는 것은 항상 나쁜 생각입니다.
Kevin McCormick
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.