[C# 객체지향] 타입 유형 확장4_구조체(Struct)

eunjin lee·2022년 7월 2일
0

C# 9.0 프로그래밍

목록 보기
12/50

int, char, bool 같은 값 형식에 class처럼 사용자 정의 형식을 두려고 할 때 구조체(struct)를 사용한다.


  1. 문법
  • 클래스와 유사하지만 다음과 같은 차이점이 있다.
  • 인스턴스 생성을 new로 해도 되고, 안 해도 된다.
  • 기본 생성자는 명시적으로 정의할 수 없다.
  • 매개변수를 갖는 생성자를 정의해도 C# 컴파일러가 자동으로 기본 생성자를 만들어 포함시킨다.
  • 매개변수를 갖는 생성자는 반드시 해당 코드 내에서 구조체의 모든 필드에 값을 할당해야 한다.
  • ✍ 샘플 코드
   class Test
    {
        static void Main(string[] args)
        {
            Vector v1 = new Vector();
            Vector v2;
            Vector v3 = new Vector(2, 3);
            
            Console.WriteLine(v1.ToString());
            // Console.WriteLine(v2.ToString()); //컴파일 에러 : 할당되지 않음.
            Console.WriteLine(v3.ToString());

            v2.x = 10;
            v2.y = 20;
            Console.WriteLine(v2.ToString());   
        }
    }

    struct Vector
    {
        public int x;
        public int y;

        public Vector(int x, int y)
        {
            this.x = x; this.y = y;
        }

        public override string ToString()
        {
            return "x = " + this.x + ", y = " + this.y;
        }
    }
  • ✅ 결과
x = 0, y = 0
x = 2, y = 3
x = 10, y = 20

v1과 v2는 컴파일러가 내부적으로 만든 기본 생성자를 통해 만들어진다. 이는 int와 같은 값 형식을 사용할 때와 동일하다.
  • ✍ 샘플 코드
// 모두 동일한 표현이다.
        static void Main(string[] args)
        {
            int n1 = new int();
            int n2;
            n2 = 0;
            int n3 = 0;

            Console.WriteLine(n1);
            Console.WriteLine(n2);
            Console.WriteLine(n3);

        }

  1. 깊은 복사와 얕은 복사
  • class 와 struct의 차이는 대입 시에 드러난다. class는 얕은 복사를 하지만, struct는 깊은 복사를 한다.
  • class를 대입할 때, 스택에는 같은 주소값이 복사된다. 그 주소값이 가리키는 값은 힙 영역에 있으며 복사되지 않는다.
  • struct를 대입할 때, 스택에는 값 자체가 복사되어 별도의 메모리에 존재한다.
  • ✍ 샘플 코드
    class Test
    {
        static void Main(string[] args)
        {
            Vector v1 = new Vector(5,10);
            Vector v2 = v1;
            v2.x = 1000;
            v2.y = 3000;
            Console.WriteLine(v1.ToString());
            Console.WriteLine(v2.ToString());

            Point p1 = new Point(4, 10);
            Point p2 = p1;
            p2.x = 2000;
            p2.y = 60000;
            Console.WriteLine(p1.ToString());
            Console.WriteLine(p2.ToString());

        }
    }

    struct Vector
    {
        public int x;
        public int y;

        public Vector(int x, int y)
        {
            this.x = x; this.y = y;
        }

        public override string ToString()
        {
            return "Vector x = " + this.x + ", y = " + this.y;
        }
    }

    class Point
    {
        public int x;
        public int y;

        public Point(int x, int y)
        {
            this.x=x; this.y=y;
        }

        public override string ToString()
        {
            return "Point x = " + this.x + ", y = " + this.y;
        }
    }
  • ✅ 결과
  Vector x = 5, y = 10
  Vector x = 1000, y = 3000
  Point x = 2000, y = 60000
  Point x = 2000, y = 60000

struct의 깊은 복사는 매개변수로 넘길 때도 동일하게 적용된다.

  • ✍ 샘플 코드
    class Test
    {
        static void Main(string[] args)
        {
            Vector v1 = new Vector(5,10);
            VectorFunction(v1);
            Console.WriteLine(v1.ToString());

            Point p1 = new Point(5,10);
            PointFunction(p1);
            Console.WriteLine(p1.ToString());

        }

        static void VectorFunction(Vector vt)
        {
            vt.x = 100;
            vt.y = 100;
        }

        static void PointFunction(Point p)
        {
            p.x = 100;
            p.y = 100;
        }
    }
  • ✅ 결과
  Vector x = 5, y = 10
  Point x = 100, y = 100

참조값만 전달하는 것이 성능 상 좋지만, 깊은 복사를 해야 한다면 struct로 구현해야 한다. 혹은 GC의 부담을 줄여주기 위해서 구조체를 선택할 수도 있다.

0개의 댓글