프로그래밍 C#언어

구조체 (Structure)

게임첫걸음 2024. 8. 29. 17:48
//Value Type (값 형식)	//값 자체를 가져오는 형식
//Reference Type (참조 형식) //주소를 가져오는 형식
//모든 클래스, 배열은 참조 형식, 값을 바꾸면 원본값도 바뀌는 방식
//클래스 복사하면 얉은 복사
struct Point
{
    //int m_iVal;
    //int mVal;

    //public int x = 100;   //구조체는 선언과 동시에 초기화가 불가능.
    public int x;
    //public int y { get; set; }
    
   
    public int y;
    public int Y  //Property(속성)
    {
        get { return y; }
        set { y = value; }
    }

    //함수 오버로딩(Function Overloading)
    //기본생성자(Default Constructor)
    //유니티에서는 사용X (매개변수 필수)
    public Point()
    {
        Console.WriteLine("Point Constrctor Call!");

        x = 0;
        y = 0;
    }

    public Point(int _x, int _y)
    {
        Console.WriteLine("Point Overload Constructor Call!");
        x = _x;
        this.y = _y;    //나 자신의 구조
    }

    public Point(Point _pt)
    {
        Console.WriteLine("Point Copy Constructor Call!");

        x = _pt.x;
        y = _pt.y;
    }

    //연산자 오버로딩(Operator Overloading)
    public static Point operator+(Point _pt1, Point _pt2)
    {
        Console.WriteLine("Point Operator + Call!");
        return new Point( _pt1.x + _pt2.x, _pt1.y + _pt2.y );
    }
}

 C언어와 마찬가지로 struct를 활용하여 구조체를 생성합니다. C#에서의 구조체에 대해 알아보겠습니다. 위의 코드는 point.cs에 작성된 코드입니다.

  • public int x = 100; // C#에서 구조체는 초기화할 수 없으므로 오류 코드
  • public int x; , public int y; // Point 구조체의 멤버 변수입니다.
  • public int Y { get; set; } // y 변수에 접근하기 위한 Y라는 속성(Property)입니다.
  • public Point( ) { ... } // 매개변수가 없는( ) 기본 생성자로 x, y를 0으로 초기화합니다.
  • public Point(int _x, int _y){ ... } // 매개변수를 받아 x와 y를 초기화하는 오버로드된 생성자입니다.
  • public Point(Point _pt){ ... } // 다른 Point 객체를 받아 그 값을 복사하는 복사 생성자
  • public static Point operator+(Point _pt1, Point _pt2){ ... } // + 연산자를 오버로딩하여 두 Point 객체를 더할 수 있는 연산자 오버로딩입니다.

이제 위의 point.cs의 코드들을 사용하는 Main함수를 가진 program.cs의 코드들을 보겠습니다.

//C# 11버전에서 사용되는 기능 가비지 컬렉션
//Garbage Collection
//Garbage Collector
//Reference Count
//게임에서는 사용하지 않는 편. 사용하면 편하지만, 실시간으로 돌아가는게 게임이기 때문에 사용안함.
//(어차피 Unity는 C# 9버전이라 안됨, 언리얼은 사용중)
class Program
{
    static void Method(int _i)
    {
        Console.WriteLine("Method with int");
    }

    static void Method(float f)
    {
        Console.WriteLine("Method with float");
    }

    static void Method(int _i1, int _i2)
    {
        Console.WriteLine("Method with int two");
    }

    static void DefaultParam(int _val1, int _val2 = 50) //DefaultParameter (매개변수의 기본값 지정(초기화) 방식)
    {
        Console.WriteLine("Default Parameter: {0} {1}", _val1, _val2);
    }

    static void Main()
    {
        //구조체
        Point ptAlloc = new Point(5, 3);
        ptAlloc.x = 100; //Point.cs의 x에 public을 붙여 가져올 수 있음.
        Console.WriteLine("({0}, {1})", ptAlloc.x, ptAlloc.Y);
   
        Point pt;
        pt.x = 100;
        pt.y = 50;
        Console.WriteLine("({0}, {1})", pt.x, pt.Y);

        Point copyPt = new Point(ptAlloc);  //구조체는 new를 붙여도 동적할당이 아님. 힙에 안들어감, 그래서 지역변수에 해당.
        Console.WriteLine("Copy: ( {0}, {1} )", copyPt.x, copyPt.y);

        Point copy = new Point();
        copy = copyPt;

        Point result = copyPt + copy;
        Console.WriteLine("result: ({0}, {1})", result.x, result.y);

        /////////////////////////////////////////////////////////////////////
        Console.WriteLine();

        Method(1);
        Method(3.14f);
        Method(1, 2);

        DefaultParam(1);    //_val1에 1 대입, _val2에는 50이 대입되어있음. (1, 2)면 _val2에 2가 대입되서 출력됨.
    }
}
  • ptAlloc은 Point(int _x, int _y), 오버로드된 생성자를 가져옵니다.
  • ptAlloc의 x = 100을 대입합니다.
  • Point pt; 는 Point(_pt), 복사 생성자를 가져옵니다.
  • pt의 x와 y에 각각 100, 50을 대입합니다.
  • copyPt는 Point(_pt), 복사 생성자를 가져오고 매개변수로 ptAlloc을 사용합니다.
  • copy는 copypt를 값 복사했습니다. copyPt의 x, y값을 복사한 구조체입니다.
  • result는 copyPt와 copy를 더한 결과를 담는 구조체이며 Point operator+, 연산자 오버로딩을 가져옵니다.

결과값

  • Point Overload Constructor Call! // ptAlloc
  • (100, 3) // ptAlloc
  • (100, 50) // pt
  • Point Copy Constructor Call! // copyPt
  • Copy: ( 100, 3 ) // copyPt
  • Point Constructor Call! // copy
  • Point Operator + Call! // result
  • Point Overload Constructor Call! // result
  • result: (200, 6) // result

<메서드>(Method)

class Program
{
    static void Method(int _i)
    {
        Console.WriteLine("Method with int");
    }

    static void Method(float f)
    {
        Console.WriteLine("Method with float");
    }

    static void Method(int _i1, int _i2)
    {
        Console.WriteLine("Method with int two");
    }

    static void DefaultParam(int _val1, int _val2 = 50) //DefaultParameter (매개변수의 기본값 지정(초기화) 방식)
    {
        Console.WriteLine("Default Parameter: {0} {1}", _val1, _val2);
    }
    static void Main()
	{
        Method(1);
        Method(3.14f);
        Method(1, 2);

        DefaultParam(1);    //_val1에 1 대입, _val2에는 50이 대입되어있음. (1, 2)면 _val2에 2가 대입되서 출력됨.
    }
}

 위는 main에서 매개변수에 따라 사용하는 메서드가 달라지는 것을 이해하기위한 코드 구성입니다.

  • 일반 정수형이면 Method with int
  • f가 붙는 실수형이면 Method with float
  • 정수형 2가지를 매개변수로 가졌다면 Method with int two

DefaultParam은 매개변수 내에서도 초기화가 가능한 것과 그 초기화가 어떤 방식으로 구현되는지 이해하기 위한 코드입니다.

  • int _val1, int _val2 = 50이면 val2에 50으로 초기화된 상태라는 뜻입니다.
  • DefaultParam(1)은 Default Parameter: 1, 50으로 _val1에 1이 대입되고 _val2는 기존의 50을 그대로 가진 상태로 출력됩니다.