Wanna be Brilliant Full-Stack Developer

C# WinForms 구조체와 클래스 본문

Some Memos/C#

C# WinForms 구조체와 클래스

Flashpacker 2023. 4. 10. 16:41

구조체와 클래스의 차이는 간단하게 데이터 형태를 가지고 가기 위해서는

보통 구조체를 쓰고 나머지경우 메서드나 함수를 많이 쓸대는 클래스를 사용한다.

전체적인 의견은 상속을 쓰지않는 경우 두개의 차이가 크지 않다고 한다.

 

제일 중요한것은 구조체는 값 타입 데이터라서  Stack Memory를 사용한다.

클래스는 Heap 메모리를 쓴다. 

 

Stack 메모리는 선언을 하지 않고 바로 사용을 하니까 초기화를 하지 않고 바로 사용한다.

 

Heap이 조금더 무겁다. 메모리 관리가 필요하다. 

클래스쪽들을 쓰면은 프로그램 무게가 나가게 된다. 

 

지금은 이정도만 알고 있으면 된다!

데이터 형만 지정해서 그안에 데이터만 넣고 싶다고하면 구조체를 사용하면 되고

그 외에 조금 복잡하고 계산이 많이 들어간 프로그램을 짜고 싶다고 하면 클래스를 사용하면 된다.

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Struct_Class
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        struct Car
        {
            int cycle;
            int window;
            int door;
            string name;
        }
    }
}

Struct는 데이터형을 정의할때 많이 쓴다.

데이터형을 하나로 그냥 가져가고 싶은데 여러가지가 있을때 하나로 가져갈수 있으니까

조금더 편하게 사용할 수 있다!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Struct_Class
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        struct Car
        {
            int cycle;
            int window;
            int door;
            string name;
        }

        class cCar
        {
            int cycle;
            int window;
            int door;
            string name;
        }
    }
}

똑같이 이렇게 해도 오류가 안뜬다.

문법적으로는 오류가 없다. 그래서 조금씩 헷갈리기 시작한다.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Struct_Class
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        struct structPlayer
        {
            public int iCount; //몇회를 진행 중인지

            public int iSun;  //해에 대한 값
            public int iMoon; // 달에 대한 값
            public int iStar; // 별에 대한 값

            public int iCardsum; // 해. 달, 별을 더한 값

            //값드를 더해서 반환
            public int CardSun(int iSun, int iMoon, int iStar) 
            { 
                return iSun + iMoon + iStar;
            }

            //결과를 String 형태로 변환 ( 화면에 결과를 보여주기 위해 사용)
            public string ResultText()
            {
                return string.Format("{0}회 해 :{1}, 달 : {2} , 별: {3} => 합계는 {4} 입니다."
                    , iCount, iSun, iMoon, iStar, iCardsum);
            }
        }

      

        private void pboxSun_Click(object sender, EventArgs e)
        {

        }

        private void pboxMoon_Click(object sender, EventArgs e)
        {

        }

        private void pboxStar_Click(object sender, EventArgs e)
        {

        }

        private void pboxNone_Click(object sender, EventArgs e)
        {

        }
    }
}

우선 구조체형식으로 만들었다!

이제 클래스 형식으로 똑같이 만들어보자! 

 

클래스는 값을 초기화 할 수도 있다.

 class classPlayer
        {
            public int iCount = 0; //몇회를 진행 중인지

            public int iSun = 2;  //해에 대한 값
            public int iMoon = 3; // 달에 대한 값
            public int iStar = 4; // 별에 대한 값

            public int iCardsum; // 해. 달, 별을 더한 값

            //값드를 더해서 반환
            public int CardSun(int iSun, int iMoon, int iStar)
            {
                return iSun + iMoon + iStar;
            }

            //결과를 String 형태로 변환 ( 화면에 결과를 보여주기 위해 사용)
            public string ResultText()
            {
                return string.Format("{0}회 해 :{1}, 달 : {2} , 별: {3} => 합계는 {4} 입니다."
                    , iCount, iSun, iMoon, iStar, iCardsum);
            }
        }

 

구조체는 초기화가 불가능하다.

 

접근제한 메소드를 작성해보려고 한다

private void iCheckedChange()
        {
            if (rdoPlayer1.Checked)
            {
                rdoPlayer2.Checked = true;
            }
            else
            {
                rdoPlayer1.Checked = true;
            }
        }
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Struct_Class
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        struct structPlayer
        {
            public int iCount; //몇회를 진행 중인지

            public int iSun;  //해에 대한 값
            public int iMoon; // 달에 대한 값
            public int iStar; // 별에 대한 값

            public int iCardsum; // 해. 달, 별을 더한 값

            //값드를 더해서 반환
            public int CardSun(int iSun, int iMoon, int iStar) 
            { 
                return iSun + iMoon + iStar;
            }

            //결과를 String 형태로 변환 ( 화면에 결과를 보여주기 위해 사용)
            public string ResultText()
            {
                return string.Format("{0}회 해 :{1}, 달 : {2} , 별: {3} => 합계는 {4} 입니다."
                    , iCount, iSun, iMoon, iStar, iCardsum);
            }
        }

        structPlayer stPlayer1;  // 1번플레이어
        structPlayer stPlayer2; //   2번플레이어

        //class classPlayer
        //{
        //    public int iCount = 0; //몇회를 진행 중인지

        //    public int iSun = 2;  //해에 대한 값
        //    public int iMoon = 3; // 달에 대한 값
        //    public int iStar = 4; // 별에 대한 값

        //    public int iCardsum; // 해. 달, 별을 더한 값

        //    //값드를 더해서 반환
        //    public int CardSun(int iSun, int iMoon, int iStar)
        //    {
        //        return iSun + iMoon + iStar;
        //    }

        //    //결과를 String 형태로 변환 ( 화면에 결과를 보여주기 위해 사용)
        //    public string ResultText()
        //    {
        //        return string.Format("{0}회 해 :{1}, 달 : {2} , 별: {3} => 합계는 {4} 입니다."
        //            , iCount, iSun, iMoon, iStar, iCardsum);
        //    }
        //}
        Random _rd = new Random();
        // 보통 전역변수 앞에는  _ 이걸 붙여서 구분하는것도 좋다.
        private void pboxSun_Click(object sender, EventArgs e)
        {
            

            int iNumber = _rd.Next(1,21);

            if (rdoPlayer1.Checked)
            {
                stPlayer1.iSun = iNumber;
            }
            else
            {
                stPlayer2.iSun = iNumber;
            }

            iCheckedChange();
        }

        private void pboxMoon_Click(object sender, EventArgs e)
        {

            int iNumber = _rd.Next(1, 21);

            if (rdoPlayer1.Checked)
            {
                stPlayer1.iMoon = iNumber;
            }
            else
            {
                stPlayer2.iMoon = iNumber;
            }

            iCheckedChange();
        }

        private void pboxStar_Click(object sender, EventArgs e)
        {

            int iNumber = _rd.Next(1, 21);

            if (rdoPlayer1.Checked)
            {
                stPlayer1.iStar = iNumber;
            }
            else
            {
                stPlayer2.iStar = iNumber;
            }


            iCheckedChange();
        }

        private void pboxNone_Click(object sender, EventArgs e)
        {
            // 아무짓도 안하고 한턴을 넘긴다.

            iCheckedChange();
        }


        private void iCheckedChange()
        {
            if (rdoPlayer1.Checked)
            {
                rdoPlayer2.Checked = true;
            }
            else
            {
                rdoPlayer1.Checked = true;
            }
        }
    }
}

이제 받은 값들을 한턴 지날때마다 다 더하고 결과를 뿌려줄것이다.

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace _11.Struct_Class
{
 
    public partial class Form1 : Form
    {
        // Player에 대한 구조체
        struct structPlayer
        {
            public int iCount;  // Player가 몇회 진행 중인지
 
            public int iSun;  // 해에 대한 값
            public int iMoon;  // 달에 대한 값
            public int iStar;  // 별에 대한 값
 
            public int iCardSum;  // 해, 달, 별을 더한 값
 
            // 값들을 더해서 반환
            public int CardSun(int iSum, int iMoon, int iStar)
            {
                return iSun + iMoon + iStar;
            }
 
            // 결과를 String 형태로 변환 (화면에 결과를 보여주기 위해 사용)
            public string ResultText()
            {
                return string.Format("{0}회) 해:{1}, 달:{2}, 별:{3} => 합계는 {4} 입니다.", iCount, iSun, iMoon, iStar, iCardSum);
            }
        }
 
 
        // Player에 대한 Class (실제 프로그램 동작과는 관계 없음)
        class classPlayer
        {
            public int iCount = 0;  // Player가 몇회 진행 중인지
 
            public int iSun = 2;  // 해에 대한 값
            public int iMoon = 3;  // 달에 대한 값
            public int iStar = 3;  // 별에 대한 값
 
            public int iCardSum = 4;  // 해, 달, 별을 더한 값
 
            // 값들을 더해서 반환
            public int CardSun(int iSum, int iMoon, int iStar)
            {
                return iSun + iMoon + iStar;
            }
 
            // 결과를 String 형태로 변환 (화면에 결과를 보여주기 위해 사용)
            public string ResultText()
            {
                return string.Format("{0}회) 해:{1}, 달:{2}, 별:{3} => 합계는 {4} 입니다.", iCount, iSun, iMoon, iStar, iCardSum);
            }
        }
 
        structPlayer _stPlayer1;  //1번 Player
        structPlayer _stPlayer2;  //2번 Player
 
        Random _rd = new Random();  // 난수 발생용
 
        classPlayer _clPlayer1 = new classPlayer();  //Test 용 
        classPlayer _clPlayer2 = new classPlayer();  //Test 용 
 
 
        /// <summary>
        /// 프로그램의 진입점 입니다.
        /// </summary>
        public Form1()
        {
            InitializeComponent();
        }
 
 
        /// <summary>
        /// 화면에서 "해" 그림을 Click 했을 때 Event를 발생 시킵니다.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pboxSun_Click(object sender, EventArgs e)
        {
            int iNumber = _rd.Next(1, 21);
 
            //어떤 Player가 선택 되어 있는지 확인
            if (rdoPlayer1.Checked)
            {
                _stPlayer1.iSun = iNumber;
 
                //_clPlayer1.iSun = iNumber;
            }
            else
            {
                _stPlayer2.iSun = iNumber;
 
                //_clPlayer2.iSun = iNumber;
            }
 
            Result();
        }
 
 
        /// <summary>
        /// 화면에서 "달" 그림을 Click 했을 때 Event를 발생 시킵니다.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pboxMoon_Click(object sender, EventArgs e)
        {
            int iNumber = _rd.Next(1, 21);
 
            //어떤 Player가 선택 되어 있는지 확인
            if (rdoPlayer1.Checked)
            {
                _stPlayer1.iMoon =iNumber;
            }
            else
            {
                _stPlayer2.iMoon = iNumber;
            }
 
            Result();
        }
 
 
        /// <summary>
        /// 화면에서 "별" 그림을 Click 했을 때 Event를 발생 시킵니다.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pboxStar_Click(object sender, EventArgs e)
        {
            int iNumber = _rd.Next(1, 21);
 
            //어떤 Player가 선택 되어 있는지 확인
            if (rdoPlayer1.Checked)
            {
                _stPlayer1.iStar =iNumber;
            }
            else
            {
                _stPlayer2.iStar = iNumber;
            }
 
            Result();
        }
 
 
        /// <summary>
        /// 화면에서 "빈" 그림을 Click 했을 때 Event를 발생 시킵니다.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pboxNone_Click(object sender, EventArgs e)
        {
            // 아무짓도 안하고 한턴을 넘긴다
 
            Result();
        }
 
        
        /// <summary>
        /// 현재 선택 된 Radio Button을 확인해서 선택되지 않은 Radio Button을 선택하기 위해 사용
        /// </summary>
        private void iCheckedChange()
        {
            //어떤 Player가 선택 되어 있는지 확인
            if (rdoPlayer1.Checked)
            {
                rdoPlayer2.Checked = true;
            }
            else
            {
                rdoPlayer1.Checked = true;
            }
        }
 
 
        /// <summary>
        /// 선택 된 Radio Button에 대해서 해, 달, 별의 값을 더하고 결과를 내용으로 만들어서 ListBox에 표시
        /// </summary>
        private void Result()
        {
            string strResult = string.Empty;
 
            //어떤 Player가 선택 되어 있는지 확인
            if (rdoPlayer1.Checked)  
            {
                _stPlayer1.iCount++;  // Player에 대한 진행 횟수를 증가
 
                _stPlayer1.iCardSum = _stPlayer1.CardSun(_stPlayer1.iSun, _stPlayer1.iMoon, _stPlayer1.iStar);  // 해, 달, 별의 값을 더해서 Player에 ICradSum에 넣어줌
 
                strResult = _stPlayer1.ResultText();  // 결과 값을 string 형태로 변환
 
                lboxResult1.Items.Add(strResult);  // 결과 값을 listbox에 등록
            }
            else
            {
                _stPlayer2.iCount++;
 
                _stPlayer2.iCardSum = _stPlayer2.CardSun(_stPlayer2.iSun, _stPlayer2.iMoon, _stPlayer2.iStar);
 
                strResult = _stPlayer2.ResultText();
 
                lboxResult2.Items.Add(strResult);
            }
 
            iCheckedChange();  // 다음 Player 선택
 
            // 결과를 체크 (Player1과 2의 진행 횟수가 5회가 넘어갈 경우 각 Player의 iCard Sum 값을 비교해서 결과를 화면에 Popup 합니다.
            if (_stPlayer1.iCount >= 5 && _stPlayer2.iCount >= 5)
            {
                if (_stPlayer1.iCardSum > _stPlayer2.iCardSum)
                {
                    MessageBox.Show("Player1이 이겼습니다.");
                }
                else if (_stPlayer1.iCardSum < _stPlayer2.iCardSum)
                {
                    MessageBox.Show("Player2가 이겼습니다.");
                }
                else
                {
                    MessageBox.Show("비겼습니다.");
                }
            }
        }
    }
}

이렇게하면 오류가 될 수 있다. 할당을 안하면 null이라는 값이 들어가 있기 때문이다.

애를 사용하기위해서는 선언을을 해야한다.

 

classPlayer _clPlayer1 = new classPlayer();
        classPlayer _clPlayer2= new classPlayer();

이렇게 하면 오류가 안뜬다.