개발언어/C#

[C#] Class vs Struct

내꺼블로그 2024. 4. 12. 10:10

정의

class

  • 객체 지향 언어에서 사용되는 중요한 형식으로, 객체를 만드는 틀 역할을 한다.
  • 생성자, 멤버변수, 메서드로 이루어져 있다.
  • 상속을 통해 클래스를 확장할 수 있다.

 

struct

  • 여러 타입의 변수를 저장하고 이를 하나의 타입으로써 사용할 수 있는 사용자 정의 타입
  • 클래스와 마찬가지로 생성자, 멤버변수, 메서드를 가질 수 있다.

 


 

차이점

1) 형식 차이

class참조 형식인 반면 struct값 형식이다.

*참조형식: 힙(Heap)이 저장되어 프로그램이 종료될 때까지 메모리에 남아있다.

                  힙(Heap)에 저장되어 있는 값의 주소스택(Stack)에 저장되어 있다.

                  힙(Heap)에 메모리를 할당하기 위해서는 new 연산자가 필요하다.

*값형식: 스택(Stack)이 저장되어 해당 메서드가 종료되면 메모리가 해제된다.

 

*예시

다음 코드를 통해 참조형식과 값형식의 차이에 대해 알아보자.

임의의 class와 struct를 선언하였다.

 

메인 메서드에 Class와 Struct를 선언한 뒤 ChangeValue 메서드를 호출 전후 각각의 값을 찍어보자.

 

선언한 ChangeValue 메서드.  매개변수의 값을 변경하고 출력하는 기능을 갖고 있다.

 

결과

class의 경우 원본의 값이 변경된 반면 struct는 값의 복사본만 변경되어 원본에는 반영되지 않은 것을 알 수 있다.

메인 메서드에 선언된 struct는 그 안에서만 값을 가지고 있기 때문에 ChangeValue로 넘어갈 때는 메인에서 선언한 struct가 아닌 새로운 struct가 생성되어 ChangeValue에서만 머무르고 있는 것이다.

ChangeValue 메서드가 종료되면 즉시 메서드에서 사용된 struct의 메모리는 해제된다.

 

 

 

 

2) new 연산자

class는 객체를 생성하기 위해 반드시 new 연산자를 사용해야 하는 반면 struct는 new 연산자를 반드시 사용할 필요 없다.

 

앞의 예제를 통해 알 수 있는 부분.

다음과 같은 코드는 불가능하다.

class는 참조형식으로 객체를 생성하기 위해(메모리 할당을 위해) new 연산자가 반드시 필요하기 때문이다.

위의 경우 class d를 선언만 한 상태에서 객체를 생성하지 않았기(메모리를 할당하지 않았기) 때문에 d.a로의 접근이 불가능한 것!

 

반면 struct는 new를 써도 가능, 안써도 가능

 

 

 

 

3) 생성자 선언

class는 생성자를 선언할 때 멤버변수 모두를 매개변수로 받지 않아도 되는 반면 struct는 생성자를 선언할 때 멤버변수들을 모두 매개변수로 받아야 된다.

 

class는 멤버변수 타입을 생성자의 매개변수로 모두 쓰지 않아도 가능

 

struct의 경우 매개변수를 받음과 동시에 할당까지 해주어야 오류가 나지 않는다.

다만 이것도 언어 버전에 따라서 가능한 영역도 있는 것으로 보인다.

오류

 

 

4) 상속 가능 유무

class는 상속이 가능한 반면 struct는 상속이 불가능하다.

 

 

 

 


 

 

class와 struct는 어떨 때 사용하는 것이 좋은가 

의미로 봤을 때는 class는 객체를 생성할 때, struct는 여러 타입의 정보를 하나의 타입으로 취급할 때 사용하면 된다.

하지만 위의 기준 자체도 모호하기 때문에 class를 사용하냐 struct를 사용하냐는 꽤 고민이 될 수 있다.

(심지어 struct도 메서드를 선언할 수 있으니 더더욱 이 둘의 차이가 안느껴질 것이다.)

 

그래서 사실 class와 struct 중 하나를 결정할 때는 위의 측면보다 성능적이 면을 더 따지게 된다.

struct는 스택에 저장되며, 사실 스택은 힙에 비해 더욱 메모리가 제한적이기 때문에 스택 메모리를 많이 잡아먹을 것 같은 구조면 class를 쓰는 것이 더 낫다.

하지만 class의 경우 힙 메모리를 사용하며, 이 힙 메모리를 관리하기 위해서는 GC(가비지 컬렉터)라는 아이가 일을 해야 하기 때문에 오히려 이러한 성능 면에서는 struct가 우위를 점하게 된다.

 

그러므로, 스택오버플로우가 일어나지 않을 것 같으면 struct, 그 외는 class를 사용하는 것이 좋다.