[C#] class와 struct

Min·2024년 7월 25일
0

CSharp

목록 보기
6/25
post-thumbnail

내가 알고있는 struct와 class에 대한 이야기

C++에서 class와 struct의 차이점은 단 하나이다. 기본 접근 제한자가 class는 private, struct는 public이라는 점이다. 그럼에도 불구하고 둘의 용도를 구분해서 사용하는 프로그래머들이 꽤 있다.

이는 C의 잔재라고 생각한다. C에서는 class라는 개념은 아얘 없었고, 사용자 정의 자료형을 만들 때 struct문법을 사용했다. struct는 여러개의 기본자료형을 하나로 묶어 사용자 정의 자료형을 만들 수 있는 문법이었다. C++로 넘어오면서 struct는 하나의 객체를 표현할 수 있는 기능으로 확장됐지만, 같은 기능을 가지고 있는 class라는 문법이 존재했다. class는 다른 언어에서도 객체지향언어의 기본단위로 많이 사용되기 때문에 오히려 직관적이기까지했다. 그렇기 때문에 복잡하고 많은 기능들을 가지고 있는 객체는 class로, 간단하고 단순한 데이터 형식의 객체는 struct로 정의하고 사용하는 사람들이 많다.

C#에서의 struct와 class

C#에서는 struct와 class는 명백하게 다르다. 이는 사용자들이 struct와 class를 구분하여 사용하는 의도 자체를 반영한 것으로 생각된다. 이를 생각하면 class와 struct의 설계 의도가 보인다.


struct

  • msdn에서 설명하는 struct
    ‘구조체 형식’은 데이터와 관련 기능을 캡슐화할 수 있는 값 형식입니다. 구조체 형식은 struct 키워드를 사용하여 정의합니다.

    여기서 말하는 값 형식이란 무엇일까?
  • msdn에서 설명하는 값 형식
    값 형식 및 참조 형식은 C# 형식의 두 가지 주요 범주입니다. 값 형식의 변수에는 형식의 인스턴스가 포함되어 있습니다. 이는 형식 인스턴스에 대한 참조를 포함하는 참조 형식의 변수와 다릅니다. 기본적으로 변수 값은 할당 시에, 인수를 메서드에 전달할 때, 그리고 메서드 결과를 반환할 때 복사됩니다. 값 형식 변수의 경우 해당 형식 인스턴스가 복사됩니다. 다음 예제에서는 해당 동작을 보여줍니다.

    요약하자면, struct 형식의 객체는, 할당 시, 전달 시, 반환 시 복사된다는 것이다.
  1. 할당 시
    대입연산자를 통해 인스턴스를 복사 생성한다.
  2. 전달 시
    Call by Value, Pass by Value
    함수로 전달되는 struct형 인자는 복사 생성된 값이라는 뜻
  3. 반환 시
    함수를 통해 반환되는 struct형 변수는 복사 생성된 데이터이다.

C++에서는 일반적으로 효율적인 메모리 관리를 위해 값형으로 데이터를 사용하기보다는 참조형으로 사용하는 경우가 많다. 그럼에도 불구하고 값형으로 사용할때를 생각해보면

1. 값형으로 데이터를 전달하는 것이 참조형으로 데이터를 전달하는 것 보다 효율적일 때.
이는 일반적으로 데이터의 메모리 크기가 주소값의 크기보다 작을때이다. 즉, 단순하고 크기가 작은 데이터들은 pass by ref보다 pass by value가 효율적일 때가 있다.

2. 참조하는 데이터를 변경하지 않고 안전하게 사용하고자 할 때.
데이터를 참조한다는 것은 Pointer나 Ref가 참조하고 있는 데이터를 공유할 수도 있다는 것이다. 그런 경우 const 키워드를 사용해서 참조하는 데이터가 변경이 되지 않는다는 것을 명시해서 값 변경이 되지 않도록 상수화 하거나, 애초에 데이터를 값형으로 복사 전달하는 방법으로 데이터의 무결성을 보장한다. 전자의 경우 참조하는 값이 사용 도중 댕글링포인터가 되지 않는다는 보장이 있다면 사용하기 편한 방법이고, 후자의 방법은 사용 도중 값이 댕글링포인터가 될수도 있을 때 사용하면 안전하다.

위 의도를 생각했을때, struct를 이용하여 작고 간단한 데이터 객체를 정의할 때 사용하면, 안전하면서도 효율적으로 사용할 수 있다는 장점이 생긴다는 것을 알 수 있다. struct를 사용해서 너무 복잡하고 거대한 객체를 만들면 성능도 떨어지고, 객체를 직접 사용하는 것이 아니기 때문에 의도와 다른 동작을 할 수도 있다.

struct 제한 사항

구조체에는 클래스 형식의 기능이 대부분 있습니다. 몇 가지 예외가 있으며 최신 버전에서는 제거된 몇 가지 예외가 있습니다.

구조체 형식은 다른 클래스 또는 구조체 형식에서 상속할 수 없으며, 클래스의 Base가 될 수 없습니다. 단, 구조체 형식은 인터페이스를 구현할 수 있습니다.
구조체 형식 내에서 종료자(소멸자)를 선언할 수 없습니다.
C# 11 이전에는 구조체 형식의 생성자가 해당 형식의 모든 인스턴스 필드를 초기화해야 합니다.


class

  • msdn에서 설명하는 class
    class로 정의된 형식은 참조 형식입니다. 런타임에 참조 형식의 변수를 선언할 때 변수는 new 연산자를 사용하여 클래스의 인스턴스를 명시적으로 만들거나 다음 예제와 같이 다른 곳에서 생성되었을 수 있는 호환되는 형식의 개체를 할당할 때까지 null 값을 포함합니다

    개체가 만들어지면 해당 특정 개체에 대해 관리되는 힙에 충분한 메모리가 할당되고 변수에는 개체 위치에 대한 참조만 포함됩니다. 개체에서 사용하는 메모리는 가비지 수집으로 알려진 CLR의 자동 메모리 관리 기능에 의해 회수됩니다. 가비지 수집에 대한 자세한 내용은 자동 메모리 관리 및 가비지 수집을 참조하세요.
  • 참조 형식
    값형식과 비교해서 할당 시, 전달 시, 반환 시로 생각해보자
  1. 할당 시
    참조형식에 데이터를 할당하는 방법은 두 가지이다.

    1) new를 통해서 동적할당하고 해당 메모리를 참조하는 방법
    처음 참조 형식의 변수를 선언할 때는 new 연산자를 통해 클래스의 인스턴스를 명시적으로 만들어야 한다고 한다. new 키워드는 인스턴스를 할당하는 키워드이다. 대상이 참조형이면 힙영역에 할당되고, 값형 지역변수라면 스택에 할당된다. 힙에 할당된 메모리는 Garbage Collection에 의해 자동으로 회수된다고 하니 delete같은 키워드를 굳이 사용할 필요가 없다.

    2) 이미 있는 클래스 객체를 대입하는 방법
    같은 클래스타입을 받는 경우, 같은 인스턴스를 공유하게 된다.

  2. 전달 시
    Call by Ref, Pass by Ref
  3. 반환 시
    Ref를 반환. 참조하고 있는 인스턴스를 복사하지 않고 그대로 반환한다.

참조형은, 데이터 전달에 대한 리소스 사용이 적고, 함수가 작동하는 스코프가 아닌 다른영역에 있는 데이터를 직접 사용할 수 있다는 장점이 있다. 때문에 크고 복잡한 객체를 정의하는데 적합하다고 할 수 있다. 다만, 참조형은 독립적인 데이터가 아니기 때문에 데이터의 무결성을 위한 안전장치를 충분히 고려해야 한다.

profile
티내는 청년

0개의 댓글

관련 채용 정보