midas+son의 크리에이티브(creative) 이야기

//struct (구조체) 생성

 

    //가비지 컬렉팅의 대상이 아니고

    //스택메모리에 할당되는 struct

    struct MyStruct

    {

        //구조체에서는 미리 할당이 안됨. class에서는 됨.

        //public int i = 10;  //에러 - 구조체에는 인스턴스 필드 이니셜라이저를 사용할 수 없습니다.

        public int i;

        public int j;


        //struct에서도 생성자를 몇가지 조건하에 만들 수있다.

        //1. 매개변수가 무조건 있을 것

        //2. 생성자 안에서 struct의 변수에 값을 모두 할당할 것


        //매개변수가 없는 생성자는 불가

        //public MyStruct()

        //{

        //}

        public MyStruct(int num1, int num2)    //인자 수가 꼭 변수 수에 맞추는 것은 아니다.

        {

            i = num1;

            j = num2;   //하나만 해도 안되고 변수 모두에 값을 할당해야 한다.

        }


        //함수는 그냥 만들 수 있다.

        public void Show()

        {

            Console.WriteLine("i : {0}, j : {1}", i, j);

        }

    }

//class생성

    class MyClass

    {

        public int i = 10;


        public void Show()

        {

            Console.WriteLine("MyClass i : {0}", i);

        }


        public override string ToString()

        {

            //return base.ToString(); //base는 부모 타입. object

            return base.ToString() +"는 i가 " + i + "입니다";

        }


        public override bool Equals(object obj)

        {

            //as로 캐스팅

            MyClass other = obj as MyClass;

            if(other != null)

            {

                if(other.i == this.i)

                {

                    return true;

                }

            }

            return false;

        }

    }


//object를 인자로 받는 Fuction함수 

static void Func1(object o)

{

MyClass my = o as MyClass;

if(my != null)

{

my.Show();

}

else

{

Console.WriteLine("MyClass가 아니다." + o.ToString() + "입니다");

}

 

 

 //메인 함수

        static void Main(string[] args)

        {

            //MyStruct s1;  //에러 - 할당 되지 않은 것은 사용 할 수 없다.

            //s1.Show();


            MyStruct s1 = new MyStruct();   //기본 생성자, 안만들어도 자동으로 있다.

            s1.Show();


            MyStruct s2;    //생성 없이 사용 방법

            s2.i = 5;       //변수에 모두 값을 할당 한다.

            s2.j = 6;

            s2.Show();      //그러면 new없이 사용 가능 하다.


            MyStruct s3 = new MyStruct(100, 200);    //별도의 생성자로 할당

            s3.Show();


            MyStruct s4 = s2;   //class같은 경우는 heap메모리에서

                                //같은 것을 참조하지만

            s2.i++;             //struct에서는 값 복사를 한다.(별개로 복사, 깊은 복사)

            s2.Show();

            s4.Show();    //결과가 다르다


//class 할당

            MyClass c1 = new MyClass(); //class는 무조건 new로 heap에 할당

            Console.WriteLine(c1.ToString());   //class 는 object 타입을 기본적으로 상속 받는다.


            MyClass c2 = new MyClass(); 

            c2.i = 10;


            if(c1 == c2)    //class는 ==로 비교하면 주소값을 비교 한다.

            {

                Console.WriteLine("c1과 c2는 같다.");

            }

            else

            {

                Console.WriteLine("c1과 c2는 다르다.");  //주소값이 다르기 떄문에 false

            }

//비교함수 재정의 하여 처리

            if (Object.Equals(c1, c2))  //MyClass의 public override bool Equals(object obj) 를 탄다.

            {

                Console.WriteLine("c1과 c2는 같다.");   //i값이 같아서 true

            }

            else

            {

                Console.WriteLine("c1과 c2는 다르다.");  

            }



            //object;

            //박싱언박싱(Boxing, Unboxing)

            //class나 struct나 기본적으로 object class를 상속받고 있어

            //object를 인자로 받는 함수에 인자로 들어 갈 수 있다.

            Func1(c1);  //class는 같은 heap 메모리에서 참조만 넘겨준다.

            Func1(s1);  //구조체를 object로 받으면 heap에 new 로 새로 생성된다.(본체는 stack에 남아있다.)

            //메모리 낭비. 복사체는 가비지컬렉터 기다림.


            Object obj = s1;    //박싱이 일어남.(stack에 있는 struct가 object 클래스에 들어가야 하므로 Stack에서 Heap으로 모두 복사된다.)

            MyStruct s5 = (MyStruct)obj; //언박싱(heap에 있는걸 Stack에 복사한다. 매우 리소스를 까먹으므로 안좋다.)


            //int, float같은 기본 형은 다 struct이다. 


            string str1 = "abc";

            string str2 = "abc";

            if(str1 == str2)

            {

                //class 타입은 주소값을 비교한다. 하지만...

                //string은 class 타입이지만 

                //너무 자주 사용되기에 이미 값비교로 override 되어있다.

                Console.WriteLine("str1 == str2는 참이다.");    //참으로 나온다.

            }

            else

            {

                Console.WriteLine("str1 == str2는 거짓이다.");

            }

}