구조체란?
우선 프로그래밍 언어에서는 변수를 선언할때 이 변수를 담아두는 그릇인 자료형을 먼저 선언하게 된다.
이 변수들을 한 곳에 모아놓고 싶을 때 같은 자료형의 변수라면 배열로 선언할 수 있겠지만 나중에 해당 변수들을 쉽게 가져오거나 혹시나 다른 자료형을 가진 변수들도 모아 놓고 싶다면 코드 관리가 점점 어려워진다.
구조체는 이러한 점을 해결하기 위해 초기 기존의 C 언어에서 만들어진 기능이다.
구조체는 데이터, 즉 하나 이상의 변수들을 모아놓고 새로운 자료형을 정의하는 도구로써 작동한다.
키워드로는 struct를 사용하여 선언해주며 내부에는 원하는 자료형을 자유롭게 사용하여 선언해 주면 된다.
struct의 데이터는 값 타입(call by Value)으로 저장되며 스택 메모리에 할당된다.
예시 코드로 살펴보자
struct ExamScore
{
public int koreanScore;
public int mathScore;
public int englishScore;
public int scienceScore;
public void ShowTotalScore()
{
int totalScore = this.koreanScore + this.mathScore + this.englishScore + this.scienceScore;
Console.WriteLine($"Total Score is {totalScore}");
}
}
성적을 담은 struct를 선언해주고 성적을 합산한 결과값을 출력해주는 함수도 선언해주자.
해당 구조체를 main문에서 선언하면 이렇게 된다.
static void Main()
{
ExamScore tomScore = new ExamScore();
tomScore.koreanScore = 98;
tomScore.mathScore = 95;
tomScore.englishScore = 93;
tomScore.scienceScore = 100;
tomScore.ShowTotalScore();
}
main문에서는 tom이라는 친구의 성적을 하나 선언해주고 tomScroe에 해당하는 변수들의 값을 선언하자
Class(클래스)
클래스는 초기의 c언어에 객체 지향 프로그래밍 개념을 추가한 c++로 넘어가면서 널리 쓰이게 된 객체 지향 프로그래밍의 핵심 개념이다.
클래스 역시 구조체(struct) 와 비슷하게 여러 데이터(변수)들과 함수들을 묶어서 하나로 추상화 시킬수 있으며 사용 방법은 struct와 비슷한 편이다. 다만 데이터를 참조 타입(call by Reference)으로 저장하며 힙 메모리에 할당시킨다.
하지만 struct와 클래스는 여러 면에서 다른점이 많은데 자세한 차이점은 아래에서 따로 언급하겠다.
우선 클래스를 선언하는 방법은 다음과 같다.
class ExamScoreClass
{
// 속성
public int koreanScore;
public int mathScore;
public int englishScore;
public int scienceScore;
public ExamScoreClass(int koreanScore, int mathScore, int englishScore, int scienceScore) // 생성자
{
this.koreanScore = koreanScore;
this.mathScore = mathScore;
this.englishScore = englishScore;
this.scienceScore = scienceScore;
}
public void ShowTotalScore()
{
int totalScore = koreanScore + mathScore + englishScore + scienceScore;
Console.WriteLine($"Total Score is {totalScore}");
}
}
struct와 비슷한 기능을 하는 class를 만들어보자
ExamScore를 담당하는 class를 선언하고 생성자를 선언해준다.
소멸자의 경우 C# 언어의 경우에서는 가비지 컬렉터가 자동으로 동작하여 메모리를 관리하기 때문에 특정 리소스를 특정 시점에 꼭 소멸시키는 경우가 아니라면 기입하지 않아도 class에 할당된 메모리는 자동으로 해제된다.
Struct와 Class의 차이점
원하는 사용자 지정 데이터 타입을 지정한다는 면에서 Struct와 Class는 비슷하지만 사실 그 이상으로 많은 차이점이 존재한다. 차이점을 잘 파악하고 사용해야 효율적인 코드 구조를 만들 수 있다.
1. 데이터 참조 형식
- Struct는 데이터를 값 형식(Value Type)으로 Stack 메모리에 할당시킨다.
- Class는 데이터를 참조 형식(Reference Type)으로 Heap 메모리에 할당시킨다. (가비지 컬렉션)
2. 상속
- Struct는 상속을 지원하지 않는다.
- Class는 상속을 지원하기 때문에 다른 클래스에서 파생되어 상속 계층 구도를 만들 수 있고 이는 객체 지향 프로그래밍의 특징인 상속의 중요한 예시중 하나이다.
3. 데이터의 불변성
- Struct 내부 데이터의 특정 값을 직접 세팅할 수 없다, 따라서 변경이 가능한 구조체를 만드는것은 구조체에 어울리지 않는다.
- Class 내부 데이터의 특정 값을 세팅해 줄 수 있고 변경이 가능하다.
4. 성능
- Struct는 값 형식으로 스택 메모리에서 데이터를 가져오기 때문에 메모리 할당과 해제가 Class보다 빠를 수 있다.
- 구조체의 크기가 작을 수록 성능면에서 유리하다.
- Class는 메모리 할당과 헤제가 느릴 수 있지만 대규모거나 복잡한 데이터를 조작할 때 더 효율적일 수 있다.
Struct를 사용하는 곳
대부분의 객체 지향 프로그래밍에서는 사용자 지정 데이터 타입을 지정해야 하는 경우 Class를 압도적으로 많이 사용하게 된다.
MS 공식 문서에서는 Struct의 경우 다음과 같은 경우에 사용하는 것을 권장하고 있다.
Choosing Between Class and Struct - Framework Design Guidelines
Learn how to decide whether to design a type as a class, or to design a type as a struct. Understand how reference types and value types differ in .NET.
learn.microsoft.com
해석하자면 구조체의 경우는 아래의 네개의 경우를 충족할 때만 사용하라고 권장한다.
- 논리적으로 단일 값을 가지며 기본 타입으로 정의해야 할 경우(int나 double과 같은)
- 인스턴스 크기를 16바이트 미만으로 가질 경우
- 데이터가 불변일 경우
- 박싱이 자주 일어나지 않는 경우
반복문 내부에서 임시객체와 같은 경우에 struct를 사용하기 좋은데 여기서 class를 사용하게 되면 상당한 빈도로 heap 메모리에 할당과 해제를 반복한다.
이 많은 경우에 가비지 컬렉션이 계속해서 동작하게 되는것은 시스템이 효율적으로 작동한다고 볼 수 없다.
다만 값을 호출하는 과정에서 class와 struct는 데이터를 참조하는 방식이 다르기 때문에 이 부분은 상황에 알맞게 수정하는 편이 바람직하다.
'C#' 카테고리의 다른 글
C# - 인터페이스(Interface) (0) | 2024.07.19 |
---|---|
C# - 라이브러리 vs 프레임워크 (2) | 2024.07.11 |
C# - 스레드(Thread) (1) | 2024.06.18 |
C# - 동기와 비동기 (Synchronous/Asynchronous) (0) | 2024.06.13 |
C# - System / Collections / Generic Collection (0) | 2024.06.11 |