C# 에서 객체의 데이터를 저장하는 방법으로 필드(Field) 와 속성(Property) 이 있습니다.
두 개념은 비슷해 보이지만, 실제로는 중요한 차이점이 있으며, 속성을 사용하는 이유도 분명합니다.
이 글에서는 둘 간의 차이 그리고 더 나아가 람다 표현식으로 표현하는 방법까지 알아보도록 하겠습니다.
필드 (Field) 란?
필드는 클래스 내부에서 데이터를 저장하는 가장 기본적인 방법입니다. 보통 private 접근 제한자로 선언하여 외부에서 직접 접근할 수 없도록 합니다. 이렇게 하면 객체 내부에서만 값을 조작할 수 있어 보호가 가능하지만, 다른 코드에서 값을 변경하거나 읽으려면 별도의 메서드를 구현해야 합니다.
예를 들어, name이라는 필드를 직접 사용하면 외부에서 값을 가져오거나 변경할 수 없습니다. 따라서 이를 위해 별도의 메서드를 만들어야 합니다.
class Person
{
// 필드 선언
private string name;
// 값을 가져오는 메서드
public string GetName()
{
return name;
}
// 값을 설정하는 메서드
public void SetName(string value)
{
name = value;
}
}
이처럼 메서드를 통해 값을 설정하고 가져오는 방식은 다소 번거롭고 코드가 길어질 수 있습니다. 이러한 문제를 해결하기 위해 속성이 사용됩니다.
속성 (Property) 이란?
속성은 필드를 감싸면서, getter / setter 기능을 활용하여 데이터를 보다 간결하게 제어할 수 있도록 하는 구조입니다. 위의 메서드 기반 접근 방식을 속성을 사용하여 단순화할 수 있습니다.
class Person
{
// 필드
private string name;
// 속성
public string Name
{
get { return name; }
set { name = value; }
}
}
이제 Name 속성을 사용하면 GetName()과 SetName() 메서드를 따로 만들지 않고도 값을 설정하고 가져올 수 있습니다.
속성은 get; 이나 set; 중 하나라도 포함되면 속성이 됩니다. 즉, get 만 있다면 읽기 전용 속성이 되고, set 만 있다면 쓰기 전용 속성이 됩니다. 아래 코드의 경우, set 이 없으므로 외부에서 변수를 설정할 수 없게 되는 효과가 있습니다.
class Person
{
// 읽기 전용 속성
public string Name { get; } = "Unknown";
}
class Person
{
// set 을 private 로 선언하여 외부 설정 불가능
public string Name { get; private set; }
}
get; 만 포함된 속성은 한 번 설정된 값을 변경할 수 없습니다.
C# 에서는 속성의 네이밍 규칙상 변수 (필드) 는 소문자로 시작하지만, 속성은 첫 글자를 대문자로 시작하는 것이 일반적입니다. 예를 들어, name이라는 필드를 감싸는 속성은 Name으로 작성하는 것이 권장됩니다.
자동 구현 속성 (Auto-Implemented Property)
속성을 만들 때 별도의 필드를 선언하지 않고, 간결하게 작성할 수도 있습니다. 이를 **자동 구현 속성(Auto-Implemented Property)**이라고 합니다.
class Person
{
public string Name { get; set; } // 자동 구현 속성
}
위 코드에서 Name 속성은 내부적으로 자동으로 필드를 생성하며, 별도의 명시적인 필드 선언이 필요 없습니다. 이는 매우 간결한 코드 작성을 가능하게 합니다.
자동 구현 속성이나 일반 속성은 다음과 같이 외부에서 사용할 수 있습니다.
Person person = new Person();
person.Name = "홍길동"; // set을 이용해 값 변경
Console.WriteLine(person.Name); // get을 이용해 값 출력
람다 표현식을 활용한 속성
가장 기본적인 형태는 단순한 값 반환입니다.
// private 필드와 메서드 사용
class Person
{
private string defaultName = "홍길동";
public string GetDefaultName()
{
return defaultName;
}
}
// 속성을 사용하여 메서드 없이 직접 접근 가능
class Person
{
public string DefaultName
{
get { return "홍길동"; }
}
}
// 람다 표현식 사용
class Person
{
public string DefaultName => "홍길동"; // 선언과 동시에 값 설정
}
또 다른 예시를 들어보겠습니다.
// 기존 방식
class Circle
{
private double radius;
public double GetRadius()
{
return radius;
}
public void SetRadius(double value)
{
radius = value;
}
public double GetArea()
{
return radius * radius * Math.PI;
}
}
// 속성 사용
class Circle
{
private double radius;
public double Radius
{
get { return radius; }
set { radius = value; }
}
public double Area
{
get { return radius * radius * Math.PI; }
}
}
// 람다 표현식 사용
class Circle
{
public double Radius { get; set; }
// 반지름을 이용해 넓이를 계산
public double Area => Radius * Radius * Math.PI;
}
// 기존 방식
class Temperature
{
private double celsius;
public double GetCelsius()
{
return celsius;
}
public void SetCelsius(double value)
{
celsius = value;
}
public double GetFahrenheit()
{
return (celsius * 9 / 5) + 32;
}
}
// 속성 사용
class Temperature
{
private double celsius;
public double Celsius
{
get { return celsius; }
set { celsius = value; }
}
public double Fahrenheit
{
get { return (celsius * 9 / 5) + 32; }
}
}
// 람다 표현식 사용
class Temperature
{
private double celsius;
public double Celsius
{ get => celsius; set => celsius = value; }
// 화씨 변환
public double Fahrenheit => (Celsius * 9 / 5) + 32;
}
이처럼 => 를 사용하면 get 접근자를 간단하게 표현할 수 있으며, 동적으로 계산된 값을 반환하는 데 유용합니다.
정리
필드는 객체의 내부 데이터를 저장하는 가장 기본적인 방법이지만, 보안과 유지보수를 고려하면 속성이 훨씬 유용합니다. 속성을 사용하면 읽기/쓰기 제어, 자동 구현 등의 기능을 활용할 수 있으며, 이는 코드의 안정성과 가독성을 높이는 데 기여합니다.
'C#' 카테고리의 다른 글
람다 표현식을 사용할 때 헤깔리는 이유 (0) | 2025.03.15 |
---|---|
delegate 를 기반으로 한 상태 기계 구현해보기 (0) | 2025.03.12 |
event Action 을 활용한 이벤트 처리 (0) | 2025.03.11 |
Static 과 Instance 그리고 Singleton (0) | 2025.03.11 |
Delegate 이해하기 (0) | 2025.03.10 |