Machineboy空

C# Property 프로퍼티 get, set 본문

언어/C#

C# Property 프로퍼티 get, set

안녕도라 2025. 2. 20. 17:42

프로퍼티(Property)의 이점

객체지향 언어라면 모름지기 '은닉성'을 표현할 수 있어야 한다.

객체의 데이터가 의도하지 않게 오염되는 것을 막아야 하기 때문.

 

클래스를 작성하다가 필드를 public으로 선언해버리고 싶은 충동이 들 때가 있다.

여차하면 의도하지 않게 데이터가 오염될 수 있다.

 

프로퍼티를 이용하면 은닉성과 편의성을 모두 잡을 수 있다.


프로퍼티(Property)의 기능을 메소드로 표현한다면?

class MyClass
{
    private int myField;		// 값은 private로 은닉성을 지키면서
    
    public int GetMyField()		// get과 set은 public으로 편의성을 가진다.
    {
    	return myField;
    }
    
    public void SetMyField(int NewValue)
    {
    	myField = NewValue;
    }
}
MyClass obj = new MyClass();

obj.SetMyField(3);
Console.WriteLine(obj.GetMyField());

프로퍼티(property) 선언

  • 접근자(Accessor, callers)
    • get 접근자 : 필드로부터 값을 읽어온다.
    • set 접근자: 필드에 값을 할당한다. // set을 생략할 경우 읽기 전용 프로퍼티가 됌
// 정석 방법
class MyClass
{
    private int myField;	// 필드
    
    public int MyProperty		// 프로퍼티
    {
    	get { return myField; }
        set { myField = value;	// set 접근자의 암묵적 매개변수 }
    }
}
MyClass obj = new MyClass();

obj.MyProperty = 3;
Console.WriteLine(obj.MyProperty);

자동 구현 프로퍼티(C#3.0 이후)

프로퍼티는 데이터의 오염에 대해선 메소드처럼 안전하고, 데이터를 다룰 때는 필드처럼 간결합니다.

public class NameCard
{
	public string Name
    {
    	get; set;
    }
    
    public string PhoneNumber
    {
    	get; set;
    }
}
public class NameCard
{
	public string Name{get; set;} = "Unknown";
    public string PhoneNumber{get; set;} = "000-0000";
}

프로퍼티의 접근한정자(access modifiers)

  • Properties have access modifiers(public, private etc) in the same way as other class members
// 자동 구현 프로퍼티일 때
class MyClass
{
    private int myField;
    
    public int MyProperty {get; private set;} = 42;
}

초기화 전용 자동구현 프로퍼티 : init 접근자 (C#9.0이후)

set 접근자처럼 외부에서 프로퍼티를 변경할 수 있지만, 객체 초기화할 때만 프로퍼티 변경이 가능하다.

public class Transaction
{
    public string From   {get; inint;}
    public string To     {get; init;}
    public int 	  Amount {get; init;}
}
Transaction tr1 = new Transaction{From = "Alice", To= "Bob", Amount = 100};

required 키워드

  • init 접근자: 프로퍼티를 객체 초기화 시에만 값을 할당할 수 있도록 했다.
  • required: 초기화가 필요한 프로퍼티를 실수로 초기화하지 않는 실수를 방지할 수 있게 해줌

객체가 초기화될 때 반드시 초기화되도록 컴파일 수준에서 강제한다.

class BirthdayInfo
{
    public required string Name{get;set;}
    public required DateTime Birthday {get; init;}
}
BirthdayInfo birth = new BirthdayInfo{Name = "서현", Birthday = new DateTime(1991,6,28)};

예제

https://exercism.org/tracks/csharp/exercises/weighing-machine/edit

 

Exercism

Learn, practice and get world-class mentoring in over 50 languages. 100% free.

exercism.org

 

1) get-only Precision property set to the constructor's precision argument

class WeighingMachine
{
    private int precision;
    
    public WeighingMachine(int precision)		// 생성자
    {
    	this.precision = precision;			// 파라미터를 필드 값에 할당
    }
    
    public int Precision				// 그 필드 값을 읽어오는 읽기 전용 프로퍼티
    {
    	get {return precision;}
    }
}
var wm = new WeighingMachine(precision: 3);

// wm.Precision == 3

 

2) Weight property throw an Exception when trying to set a negative weight

class WeighingMachine
{
    private double weight;
    
    public double Weight
    {
    	get {return weight;}
        set { weight = value;
        	if(value <= 0) throw new ArgumentOutOfRangeException();	// set값 조건 설정
        }
    }
}

 

3) TareAdjustment property , 5 as its default value

class WeighingMachine
{
    private double tareAdjustment = 5;	// default값 설정
    
    public double TareAdjustment
    {
    	set { tareAdjustment = value;}
    }
}

 

4) DisplayWeight property , showing the weight after tare adjustment, with the correct precision applied

class WeighingMachine
{
    private string displayWeight;
    
    public string DisplayWeight
    {
    	get { return Math.Round(weight - tareAdjustment, precision).ToString($"F{precision}") + " kg";}
    }
}

 

전체 코드

using System;

class WeighingMachine
{
    private int precision;
    private double weight;
    private double tareAdjustment = 5;
    private string displayWeight;

    public WeighingMachine(int precision)
    {
        this.precision = precision;
    }
    
    // TODO: define the 'Precision' property
    public int Precision
    {
        get { return precision;}
    }

    // TODO: define the 'Weight' property
    public double Weight
    {
        get { return weight;}
        set { weight = value;
             if(value <= 0) throw new ArgumentOutOfRangeException();
            }
    }

    // TODO: define the 'DisplayWeight' property
    public string DisplayWeight
    {
        get { return Math.Round(weight - tareAdjustment, precision).ToString($"F{precision}") + " kg";}
    }

    // TODO: define the 'TareAdjustment' property
    public double TareAdjustment
    {
        set { tareAdjustment = value;}
    }
    
}