델리게이트(delegate) #1



delegate 뜻은 대리인,(집단의 의사를 대표하는) 대표(자)라는 뜻이 있다 무엇인가를'대신'해주는 느낌이다.


델리게이트는 메서드를 다른 메서드로 전달할 수 있도록 하기 위해 만들어 졌다.


정의

delegate string MyDelegate(string s);

델리게이트 선언의 중요점은 입력 파라미터와 리턴 타입이다.

사용하려는 메서드는 입력 파라미터타입및 갯수, 리턴타입이 같아야 한다.


객체 생성

MyDelegate del = new MyDelegate(Stringtest);

클래스 객체를 생성하는 것과 비슷한 방식으로 new를 통해 생성한다. 괄호 안에는 사용할 메서드명을 넣어 준다.


델리게이트 전달

del = new new MyDelegate(Stringtest);

Testdel(del);


void Testdel(MyDelegate m)

{

s1s2 = m("gogo");

}

델리게이트 객체를 메서드 호출 파라미터에 넣으면 된다.



 

참조 : http://www.csharpstudy.com/CSharp/CSharp-delegate-concept.aspx

오버로딩,오버라이딩


오버로딩, 오버라이딩 두개 이름이 비슷하지만 다른 재정의 기법이다.


오버로딩(Overloading)

하나의 클래스 안에 같은 이름으로 메서드를 재정의한다.

이름은 같게 하되 매개변수의 개수 및 타입정보는 다르하면 된다.

(2번째 메서드만 에러가 나는데 첫 번째 메서드의 매개변수의 정보가 같아서 이다.)

오버 로딩은 언제 쓰나?

유사하거나 동일한 결과를 출력하는 메서드가 전달 받는 매개변수에 따라 다른 연산을 해야 하는 경우에 사용된다.

메서드마다 다른 이름을 정의 하는것 보다는 직관적이고 편리해진다. 



오버라이딩(Overriding)

오버라이딩은 상위 클래스에서 선언된 함수를 하위 클래스에서 재정의하는 것

즉 이미 정의된 메서드를 재 사용 하는 것이다.

부모클래스의 메서드는 virtual키워드를 자식클래스의 메서드는 override를 꼭 선언해야한다.

오버라이딩은 다형성을 잘 나타내는 기법이다. 

<결과>

예를 들어 Animal이라는 부모 클래스에서 "동물을 짖는다"라는 메서드를 정의했다. 

그리고 자식 클래스로 Dog,Cat클래스를 만들고 Animal클래스의 "동물은 짖는다"라는 메서드를 override하여 "멍멍","냐옹냐옹"을 추가하여 재정의 하였다. 

고양이와 강아지는 공통적으로 짖는다 라는 메서드를 사용하지만 또 각각 짖는 방법이 다르기 때문이다.

게임속에서 생각해보면 공격이라는 메서드를 갖고있는 오브젝트들이 있다고 하면 그 오브젝트들은 다른 공격 스타일을 갖고 있을 것이다.



참고 : http://www.mkexdev.net/Article/Content.aspx?parentCategoryID=1&categoryID=5&ID=675

https://itmining.tistory.com/36

스태틱Static 변수


스태틱 변수는 객체를 선언만 해도 메모리가 할당되며 일반적인 변수들이 객체가 새로 생성될 때 메모리가 초기화 되는 것과 다르게 해당 객체를 계속 반복적으로 생성해도 메모리가 유지 된다는 특징이 있다. 

테스트를 해봤다

        public class Myclass

        { 

        private static int stNum= 0;

        private int num = 0;


        public Myclass()

        {

                stNum++;

                num++;

        }

     

        public void Showtest()

        {

            Console.WriteLine("stNum: {0},  num : {1}", stNum, num);

        }


    }

        static void Main(string[] args)

        {

            for (int i = 0; i < 5; i++)

            {

                Myclass test = new Myclass();

                test.Showtest();

            }

        }

    }


일반 변수인 num의 값은 변하지 않지만 Static으로 선언한 stNum은 메모리를 초기화 하지 않고 계속 더해 지고 있다. 

=> static 필드는 프로그램 실행 후 해당 클래스가 처음으로 사용될 때 한번 초기화되어

 계속 동일한 메모리를 사용하게 된다. 






스태틱Static 메소드



Static메소드는 객체가 메모리를 할당 받기 전에 호출이 되기 때문에 객체 생성 후 메모리 할당을 받는 일반 변수에 접근이 불가능하다. 인스턴스 메소드와 다르게 클래스로 객체를 따로 생성하지 않고 [클래스명.메서드명]이런식으로 호출하게 된다.

호출 시 일반 인스턴스 메서드와 달리 클래스로 부터 객체를 생성하지 않고 직접 호출한다. 



일반 인스턴스 메서드는 클래스로부터 객체를 생성하고 메서드를 호출해야하지만

static메서드는 [클래스명.메서드명]으로 메서드를 호출한다.


static메소드 내부에서 객체 멤버를 호출 할 수없다.

인스턴스 메서드는 스태틱메서드 멤버를 참조가 가능하지만 스태틱메서드는 다른 멤버 참조가 불가능하다.






스태틱Static 클래스



Static 클래스는 모든 클래스 멤버가 static 멤버로 되어 있으며, 클래스명 앞에 static이 붙는다.

다른 일반 클래스와 다르게 static생성자를 갖는다. 이 생성자는 보통 static필드를 초기화 할 때 사용한다.


테스트를 해보았다.



static 멤버 호출


객체 생성 불가

static는 인스턴스화 하지 않는 클래스이기 때문에 객체생성이 불가능하다.


 

스태틱객체는 프로그램이 종료되기 전까지 메모리를 해제하지 않고 객체를 생성하지 않고도 멤버에 접근이 가능하다는 장점 (특징)을 잘 활용해야 할 것같다. 하지만 단점으로 여러군데서 스태틱 멤버를 동시에 참조하게 될 경우와 객체 지향에 벗어난 개념이 되어 안좋다는 시선도 있다고 한다. 다른 장단점을 알아 볼 필요가 있겠다.



 참조 : http://www.csharpstudy.com/csharp/CSharp-static.aspx 사이트

http://ronniej.sfuh.tk/ , http://mygumi.tistory.com/253 ,http://blog.acronym.co.kr/347 블로그 





'프로그래밍언어 > C#' 카테고리의 다른 글

C#) 델리게이트 #2  (0) 2019.01.24
C#) 델리게이트(delegate) #1  (0) 2019.01.23
C#) 스택(Stack), 힙(Heap) 메모리구조  (0) 2019.01.15
C#)기본 개념 interface 인터페이스  (0) 2018.12.20
C#) continue , break 키워드  (0) 2018.11.14

스택(Stack), 힙(Heap) 메모리구조


우리가 어떤 동작을 할때(프로그램을 키거나) 운영체제는 그동작을 할 수 있게 메모리공간을 할당해준다.

그 할당해주는 메모리구조중 스택과 힙에 대해서 알아보자


스택 Stack 

프로그램은 함수의 호출로써 작동되는데 함수는 다른 함수를 호출하고 그 함수는 또 다른 함수를 호출하게된다. 함수들은 자신을 호출한 함수에게 결과를 반환한다.  함수 호출을 스택구조로 메모리에 차곡차곡  쌓고 처리가 끝나면 메모리에서 해제된다.

스택 메모리는 영역은 값 형식이다.

int a = 100;

int b = a;

b = 200;

a = 100;

a를 100으로 초기화하고 b는 a값을 넣어준다.

그리고 다시 b에는 200을 넣어주고 a는 100을 넣어준다.

결국은 a와 b는 마지막에 넣은100,200이 값이 되는것을 알 수있다.

스택메모리는 변수가 할당되었던 위치에 값만 변경되는것이다.

그리고 ,스택은 함수 호출 시 생성되는 지역 변수와 매개 변수가 저장되는 영역이며 함수 호출이 완료되면 해제한다.


힙 Heap

스택과 다르게 관리가 가능한(=사용자가 직접) 데이터 외에 다른 형태의 데이터를 관리하기 위한 빈 공간이라 생각하자

이 빈 공간은 동적생성된 변수를 관리 하기 위한 공간이다. 

힙 메모리 영역은 참조 형식이다.

Program p1 = new Program();

p1.value =200;

Program p2 = p1;

p2.value  = 100;

p를 동적 생성하고 값을 100을 넣어준다.

그리고 p2에 p1객체를 넣는다. 이 과정은 Stack에서의 복사가 이루어 진것이다.

p1이 참조하고있는 주소가 1000이라고 하면 p2 주소도 1000을 참조하게 된 것이다.

당연히 주소1000은 200을 참조하고 있으니 p2도 200을 참조하게 된다.

스택메모리에는 주소1000이 저장되고 힙메모리에는 값 200을 갖게된다.

네 번째줄  코드에서는 다시 100을 넣는다. 

당연히 같은 주소를 갖고있으니 p1,p2는 둘다 100을 값을 갖게 된다.

추가적인 특징으로 스택에는 메모리가 해제되는 시점이 있지만 힙에는 딱히 정해진 시점이 없다.

가비지콜렉터가 알아서 할당을 해제하기 때문이다. 

new로 동적 생성한 객체는 메모리는 힙에 만들어 지는 것과 동시에 가비지 콜렉터가 관리 되어 크게 신경쓸 필요는 없지만

가비지 콜렉터가 있으면 성능상으로 좋지 않다고 한다.


ref를 이용한 참조타입과 값타입 차이




인터페이스 interface


 클래스를 만들 때 사용하는 규약?



기본구조

interface [인터페이스 이름]

{

}



생성위치

인터페이스는 클래스와 동급의 카테고리이다. 그렇기 때문에 클래스를 생성하는 위치라면 어디든지 만들 수 있다.



예제를 보면서 이해하자



1) 인터페이스 생성

interface IBasic

{

int TestInstanceMethod( );

int TestProperty{  get; set ;}

}

메서드에 내부 구현을 입력할 수 없다.

속성에도 마찬가지로 내부 구현을 입력할 수 없다.


2) 인터페이스 상속

class TestClass : IBasic

{


}

static void Main(string[] args)

{

}


3) 인터페이스 구현

'Ctrl' + '.' 누르면 자동완성 

class TestClass : IBasic

{

public int TestInstanceMethod( )

{

throw new NotImplementedException( );

}

public int TestProperty

{

get

{

throw new NotImplementedException( );

}

set

{

throw new NotImplementedException( );

}

}

}

클래스에서 이후에 구현해준다.



4) 인터페이스 다중 상속

class Program

{


class Parent{ }

class Child : Parent, IDisposable, IComparable

{

public void Dispose( )

{

throw new NotImplementedException( );

}


public int CompareTo(object obj)

{

throw new NotImplementedException( );

}

}

//한 개의 클래스와 두 개의 인터페이스를 상속받는다.


이렇게 상속되면 다음과 같이 세종류로 자료형 변환이 가능해진다.

Child child = new Child( );

Parent ChildAsParent = new Child( );

IDisposable childAsDisposable = new Child( );

IComparable childAsComparable = new Child( );






break 키워드


조건문 또는 반복문을 벗어날 때에 사용하는 키워드입니다.


ex)


while (true)

{

Console.writeLine("무한반복문");

}


위 예같은 경우 계속 while문 안에있는 문장을 반복해서 출력하겠죠??


ex)

while (true)

{

Console.WriteLine("숫자를 입력해주세요(홀수를 입력하면 종료):");

int input = int.Parse(Console.ReadLine());


if (input % 2 == 1)

{

break;

}

}


이 예제는 어때요??

짝수를 입력하면 계속 실행하고

홀수를 입력하면 if문을 통해 break키워드가 실행되면서 바로 종료가 됩니다.




continue 키워드


반복문 내부에서 현재 반복을 멈추고 다음 반복을 진행하는 키워드입니다.


ex)

for(int i=1; i<=10; i++)

{

if(i%2==0)

{

continue; //짝수이면 다음 반복문으로 넘어갑니다. 아래코드 실행X

}

Console.WriteLine(i);

}


break문과 continue문을 활용하여 반복,조건문을 잘 활용 하시면 되겠습니다~

하지만 너무많은 사용은 코드의 가독성과 유지보수가 좋지 않기 때문에

남용은 좋지 않다고 하네요~





+ Recent posts