게터, 세터 및 속성 모범 사례. 자바 대 C #


92

저는 지금 C # 수업을 듣고 있으며 최선의 방법을 찾으려고 노력하고 있습니다. 저는 Java 배경에서 왔으므로 Java 모범 사례에만 익숙합니다. 저는 C # 초보자입니다!

Java에서 개인 속성이 있으면 이렇게합니다.

private String name;

public void setName(String name) {
   this.name = name;
}

public String getName() {
   return this.name;
}

C #에서는 여러 가지 방법이 있음을 알 수 있습니다.

Java처럼 할 수 있습니다.

private string name;

public void setName(string name) {
   this.name = name;
}

public string getName() {
   return this.name;
}

또는 이렇게 할 수 있습니다.

private string name;

public string Name {
   get { return name; }
   set { name = value; }
}

또는:

public string Name { get; set; }

어떤 것을 사용해야하며 각 접근 방식과 관련된주의 사항이나 미묘한 점은 무엇입니까? 클래스를 만들 때 Java에서 알고있는 일반적인 모범 사례를 따르고 있습니다 (특히 효과적인 Java 읽기). 예를 들어, 저는 불변성을 선호합니다 (필요한 경우에만 setter 제공). 저는 이러한 관행이 C #에서 setter와 getter를 제공하는 다양한 방법에 어떻게 적용되는지 궁금합니다. 본질적으로 Java 세계의 모범 사례를 C #으로 어떻게 변환합니까?

편집하다

나는 이것을 Jon Skeet의 답변에 대한 의견으로 게시했지만 오래되었습니다.

사소하지 않은 속성 (즉, 상당한 처리 및 유효성 검사 포함)은 어떻습니까? 나는 아직도 공용 속성을 통해 만에 캡슐화 된 논리에 노출 수 getset? 전용 setter 및 getter 메서드 (관련 처리 및 유효성 검사 논리 포함)를 사용하여이 작업을 수행해야하는 이유는 무엇입니까?

답변:


88

C # 6 이전

나는 사소한 속성을 위해 이들 중 마지막을 사용할 것입니다. getter와 setter가 모두 공용 이므로 이것을 공용 속성이라고합니다.

불변성은 자동으로 구현 된 속성으로 인해 약간의 고통입니다. getter 만있는 자동 속성을 작성할 수 없습니다. 가장 가까운 곳은 다음과 같습니다.

public string Foo { get; private set; }

이것은 정말로 불변 하지 않습니다 . 클래스 밖에서는 불변입니다. 따라서 실제 읽기 전용 속성을 대신 사용할 수 있습니다 .

private readonly string foo;
public string Foo { get { return foo; } }

당신은 확실히 쓰고 싶지 않아 getName()setName(). 에서 일부 의 경우 그것은 그들이 비싼 수있는 경우 특히, 쓰기 가져 오기 / 설정 방법보다는 사용하여 속성에 의미가 있습니다 그리고 당신은 그것을 강조하고 싶습니다. 그러나 메서드에 대한 PascalCase의 .NET 명명 규칙을 따르고 싶을 것이고 어쨌든 일반적인 메서드로 이와 같은 사소한 속성이 구현되는 것을 원하지 않을 것입니다. 여기서 속성은 훨씬 더 관용적입니다.

C # 6

만세, 마침내 적절한 읽기 전용 자동 구현 속성이 있습니다.

// This can only be assigned to within the constructor
public string Foo { get; }

마찬가지로 일부 작업 을 수행 해야하는 읽기 전용 속성의 경우 멤버 본문 속성을 사용할 수 있습니다.

public double Area => height * width;

5
더 정확하게 말하면 모든 코드는 자바 방식이 유효한 langauge AND (!) 런타임 구조를 우회하고 속성의 사용을 proeprty (예 : object.property = "value")로 죽이는 해킹이라고 지적합니다. 어떤 팀에서 이것은 태도에 대해 좋은 이야기를하게 될 것입니다.-그 태도를 경쟁자에게 사용하기위한 인센티브와 결합 된 선임에 따라 다릅니다. 진지하게, 언어와 싸우지 마십시오. 특히 자바의 "방법"은 부동산 지원을 위해 언어를 수정하지 않기 위해 선택한 해킹입니다.
TomTom

1
좋은 소식은 제 답변이 당신이 언급 한 것과 모순되지 않는다는 것입니다. 나쁜 소식은 당신의 손가락이 내 것보다 훨씬 빠르다는 것입니다. 훌륭한 통찰력과 추가 된 세부 사항에 감사드립니다.
jeremyalan

4
편집에 대한 대답 : 원하는 양의 논리와 함께 get / set 메서드를 사용할 수 있습니다. 특히 유효성 검사를 위해이 작업을 자주 수행합니다. 그러나 가장 좋은 방법은 속성에 느린 논리 (예 : 데이터베이스 액세스), 위험한 논리 (예외 발생) 또는 변형 (많은 상태 변경)을 많이 사용하지 않는 것입니다. 속성은 다소 단순한 상태처럼 작동 할 것으로 예상됩니다. 그 이상은 함수를 사용하여 표시해야합니다.
CodexArcanum

2
@rtindru : 네, 알고 있습니다. 읽기 전용 속성을 작성하는 것은 전적으로 가능합니다. 그러나 set 접근 자 없이는 자동으로 구현 된 속성을 선언 할 수 없습니다 .
Jon Skeet


17

일부 데이터를 저장할 변수 만 있으면됩니다.

public string Name { get; set; }

읽기 전용으로 표시 하시겠습니까?

public string Name { get; private set; }

또는 더 나은 ...

private readonly string _name;

...

public string Name { get { return _name; } }

속성을 할당하기 전에 값을 확인하고 싶으십니까?

public string Name 
{
   get { return m_name; }
   set
   {
      if (value == null)
         throw new ArgumentNullException("value");

      m_name = value;
   }
}

일반적으로 GetXyz () 및 SetXyz ()는 특정 경우에만 사용되며, 옳다고 느껴질 때 직감을 사용해야합니다. 일반적으로 대부분의 get / set 속성은 많은 논리를 포함하지 않고 예상치 못한 부작용이 거의 없을 것으로 예상합니다. 속성 값을 읽는 것은 서비스를 호출하거나 내가 요청하고있어 그 객체를 구축하기 위해 사용자의 입력을 받고 필요한 경우, 나는이 방법으로 포장하고, 같은 호출 것 BuildXyz()보다는, GetXyz().


2
나는 속성에서 예외를 던지지 않고 오히려 계약과 함께 메서드 setter를 사용하여 그러한 특정 동작을 지정하고 싶습니다. 속성이 int 유형이면 모든 int가 한정 될 것으로 예상합니다. 예외 발생을 요구하는 것은 내 의견으로 는 간단 하지 않습니다 . INotifyPropertyChanged 유형 호출은 저에 따라 그 줄에 더 많습니다.
flindeberg

3
private setter! = 불변
piedar

piedar가 맞습니다. private setter는 할당을 할 수 없음을 의미하지만 myList.Add(), 예를 들어를 계속 사용할 수 있습니다 (객체가 변경에 노출되는 한 변경 가능).

1
@flindeberg 죄송하지만 동의하지 않습니다 ... Min/ Max값 이있는 진행률 표시 줄이 있으면 어떨까요? 당신은 그것을 확인하고 Max > Min싶습니까? SetRange(Min, Max)의미 가 있을 수 있지만 그 값을 어떻게 다시 읽을 수 있습니까? 읽기 전용 최소 / 최대 속성? 유효하지 않은 입력에 대한 예외를 던지는 것이 이것을 처리하는 가장 깨끗한 방법 인 것 같습니다.
Basic

12

get / set 메서드가 아닌 C #의 속성을 사용합니다. 그들은 당신의 편의를 위해 거기에 있으며 관용적입니다.

두 가지 C # 예제의 경우 하나는 다른 하나의 구문 설탕입니다. 인스턴스 변수를 둘러싼 간단한 래퍼 만 있으면 auto 속성을 사용하고, getter 및 / 또는 setter에 논리를 추가해야 할 때 전체 버전을 사용하십시오.


5

C #에서는 get 및 / 또는 set에 대한 개인 필드를 노출하는 속성을 선호합니다. 언급 한 양식은 get 및 set가 숨겨진 피벗 지원 필드를 자동으로 생성하는 자동 속성입니다.

가능한 경우 자동 속성을 선호하지만 C #에서 set / get 메서드 쌍을 수행해서는 안됩니다.


5
public string Name { get; set; }

이것은 단순히 자동 구현 된 속성입니다. 이며 기술적으로 일반 속성과 동일합니다. 컴파일 할 때 백업 필드가 생성됩니다.

모든 속성은 결국 함수로 변환되므로 결국 실제 컴파일 된 구현은 Java에서 사용하는 것과 동일합니다.

지원 필드에서 특정 작업을 수행 할 필요가없는 경우 자동 구현 속성을 사용합니다. 그렇지 않으면 일반 속성을 사용하십시오. 작업에 부작용이 있거나 계산 비용이 많이 드는 경우 get 및 set 함수를 사용하고 그렇지 않으면 속성을 사용합니다.


4

C #에서 어떤 방법을 선택하든 최종 결과는 동일합니다. 별도의 getter 및 setter 메서드를 사용하여 backinng 변수를 얻습니다. 속성을 사용하면 모범 사례를 따르므로 원하는 정보를 얼마나 장황하게 볼 수 있는지가 중요합니다.

개인적으로 public string Name { get; set; }가장 적은 공간을 차지하기 때문에 마지막 버전 인 자동 속성을 선택 합니다. 그리고 유효성 검사와 같은 것을 추가해야하는 경우 나중에 언제든지 확장 할 수 있습니다.


4

가능한 한 string Name { get; set; }간결하고 쉽게 읽을 수있는 공개 를 선호합니다 . 그러나 이것이 필요할 때가 있습니다.

private string name;

public string Name {
   get { return name; }
   set { name = value; }
}

2
그런 것이 필요한시기와 이유를 설명해 주시겠습니까?
Jesper

지금은 두 번째 버전을 사용하는 이유를 생각할 수 없습니다. 나는 '이것이 필요할 때가 될 수있다'고만 말했다. 내가 긍정하지 않는 한 절대를 사용하는 것을 싫어합니다.
SquidScareMe

3
이게 왜 'lolz'일까요? 찬성하여 댓글에 대한지지를 표시 할 수 있습니다.
SquidScareMe

1
당신이 값에 원자 / 스레드 안전 작업을 수행 할 때 명시 적지지 필드를 사용하는 한 가지 이유는
기본

4

C #에서 선호되는 방법은 getX()setX()메서드가 입니다. 또한 C #에서는 속성에 가져 오기 및 집합이 모두 있어야하는 것은 아닙니다. 가져 오기 전용 속성과 설정 전용 속성을 가질 수 있습니다.

public boolean MyProperty
{
    get { return something; }
}

public boolean MyProperty
{
    set { this.something = value; }
}

4

먼저 당신이 쓴 내용을 설명하겠습니다.

// private member -- not a property
private string name;

/// public method -- not a property
public void setName(string name) {
   this.name = name;
}

/// public method -- not a property
public string getName() {
   return this.name;
}

// yes it is property structure before .Net 3.0
private string name;
public string Name {
   get { return name; }
   set { name = value; }
}

이 구조는 오늘날에도 사용되지만 일부 추가 기능을 수행하려는 경우 가장 적합합니다. 예를 들어 값이 설정된 경우 구문 분석하여 대문자로 전환하고 내부 사용을 위해 개인 멤버에 저장할 수 있습니다.

.net Framework 3.0 사용

// this style is introduced, which is more common, and suppose to be best
public string Name { get; set; }

//You can more customize it
public string Name
{
    get;
    private set;    // means value could be set internally, and accessed through out
}

C #에서 더 나은 행운을 빕니다


3

언급했듯이 이러한 접근 방식은 모두 동일한 결과를 가져옵니다. 가장 중요한 것은 컨벤션을 선택하고이를 고수하는 것입니다. 마지막 두 가지 속성 예제를 사용하는 것이 좋습니다.


2

여기에있는 대부분의 답변과 마찬가지로 자동 속성을 사용합니다. 직관적이고 코드 줄이 적고 더 깔끔합니다. 클래스를 직렬화해야하는 경우 클래스 [Serializable]/ [DataConract]속성을 표시하십시오 . 그리고 [DataContract]마크 를 사용하는 경우

[DataMember(Name="aMoreFriendlyName")]
public string Name { get; set; }

개인 또는 공용 세터는 선호도에 따라 다릅니다.

또한 자동 속성에는 getter와 setter (공용 또는 개인)가 모두 필요합니다.

/*this is invalid*/
public string Name 
{ 
    get; 
   /* setter omitted to prove the point*/
}

또는 가져 오기 / 설정 만 원하는 경우 직접 백업 필드를 만듭니다.


0

어떤 것을 사용해야하며 각 접근 방식과 관련된주의 사항이나 미묘한 점은 무엇입니까?

속성을 사용할 때 아직 언급되지 않은 한 가지주의 사항이 있습니다. 속성을 사용하면 getter 또는 setter를 매개 변수화 할 수 없습니다.

예를 들어 목록 항목을 검색하고 동시에 필터도 적용하려고한다고 가정 해보십시오. get-method를 사용하면 다음과 같이 작성할 수 있습니다.

obj.getItems(filter);

반대로 속성을 사용하면 먼저 모든 항목을 반환해야합니다.

obj.items

그런 다음 다음 단계에서 필터를 적용하거나 다른 기준으로 필터링 된 항목을 노출하는 전용 속성을 추가해야합니다. 그러면 곧 API가 팽창합니다.

obj.itemsFilteredByX
obj.itemsFilteredByY

때때로 성가신 것은 속성으로 시작한 obj.items다음 나중에 getter- 또는 setter-parametrization이 필요하거나 클래스 API 사용자를 위해 일을 더 쉽게 만드는 것을 발견 했을 때 입니다. 이제 API를 다시 작성하고이 속성에 액세스하는 코드의 모든 위치를 수정하거나 대체 솔루션을 찾아야합니다. 반대로 get-method (예 :) obj.getItems()를 사용하면 메서드 obj.getItems(options)를 호출하는 모든 위치를 다시 작성하지 않고도 선택적 "구성"개체를 허용하도록 메서드의 서명을 확장 할 수 있습니다 .

즉, 대부분의 시간 매개 변수화가 필요하지 않을 수 있기 때문에 C #의 (자동 구현 된) 속성은 여전히 ​​매우 유용한 단축키입니다 (여기에 언급 된 다양한 이유로).

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