0322 대리자 delegate★★

2021. 3. 22. 18:21C#/수업내용

대리자: 특정 매개변수 목록 및 반환 형식이 있는 메서드에 대한 참조 형식

대리자를 인스턴스화 할 수 있고,  모든 메서드가 있는 인스턴스를 반환 형식에 연결할 수 있다.

대리자를 통해 메서드를 호출할 수 있다.

 

대리자는 메서드를 다른 메서드에 매개 변수로 전달

 delegate 키워드 사용, 반환 형식, 이름, 매개변수

 

엑세스 가능한 클래스/대리자 형식과 일치하는 구조의 모든 메서드는

반환형식+매개변수가 일치해야 한다.

 

대리자는 콜백 메서드 정의에 이상적이다. 

※ 콜백: 다른 코드의 인수로 넘겨주는 실행 가능한 코드

 

매개변수를 메서드로 넘겨받을 수 있다.

 

대리자를 선언합니다.

public delegate void Del(string message);

 

public class App
    {
        //1. delegate 선언
        public delegate void Del(string message);
        public App()   
        {
            Console.WriteLine("App");
            //3. 델리게이트 인스턴스화 (델리게이트에 메서드 연결)
            Del handler = this.DelegateMethod;

            //4. 델리게이트 호출
            handler("Hello World");
            MethodWithCallback(handler);
        }
        //2. 델리게이트 메서드 정의
        public void DelegateMethod(string message) 
        {
            Console.WriteLine(message);
        }

        //콜백 메서드 정의
        public void MethodWithCallback(Del callback) 
        {
            //4. 델리게이트 호출
            callback("Hello World");
        }
    }

1. 델리게이트 선언

2. 델리게이트 메서드 정의

3. 델리게이트 인스턴스화 (메서드 연결)

4. 델리게이트 호출

public class Marine
    {
        //1. 델리게이트 형식선언
        public delegate void DelEndAttack();
        //맴버 변수 선언(델리게이트)
        public DelEndAttack endAttack;

        //생성자
        public Marine() 
        {
            
        }
        public void Attack(Zergling zergling) 
        {
            Console.WriteLine(zergling + "을 공격했습니다.");
            zergling.Hit(6);

            this.endAttack();       
     
        }
        //2. 메서드 정의
        public void EndAttack() 
        {
            Console.WriteLine("공격이 끝났습니다.");
        }
    }
public class Zergling
    {
        private int hp;
        private int maxHp;
        public Zergling() 
        { 
            this.maxHp = 35;
            this.hp = this.maxHp;
        }
        public void Hit(int damage) 
        {
            Console.WriteLine("피해({0})를 입었습니다.",damage);
            this.hp -= damage;
            Console.WriteLine("{0}/{1}", this.hp, this.maxHp);
        }
    }
public class App
    {
        public App()   
        {
            Console.WriteLine("App");
            //마린 생성
            Marine marine = new Marine();
            marine.endAttack = EndAttack;

            //저글링 생성
            Zergling zergling = new Zergling();

            marine.Attack(zergling);
        }
        public void EndAttack() 
        {
            Console.WriteLine("이펙트 생성");
        }
    }

델리게이트는 항상 메서드 정의 전에 호출 해야 함.

public class App
    {
        //생성자 
        public App() {
            Console.WriteLine("App");

            //마린생성 
            Marine marine = new Marine();

            //마린아 이동완료후 알려줘 
            //3-2. 델리게이트 인스턴스화 
            marine.moveComplete = this.MoveComplete;

            //마린이동 -> 이동완료 
            marine.Move();
        }

        //2. 마린 델리게이트에 연결할 메서드 정의 
        private void MoveComplete() {
            Console.WriteLine("[App] 마린 이동완료");
        }

    }
//1. 델리게이트 선언
    public delegate void DelMoveComple();

    public class Marine
    {
        //3-1. 델리게이트 변수선언 
        public DelMoveComple moveComplete;

        //생성자 
        public Marine() { 
        }

        public void Move() {
            //4. 델리게이트 호출 
            Console.WriteLine("[Marine] 마린 이동합니다.");
            this.moveComplete();
        }
    }

※상태 변화 알리기가 대부분

상태 변화 시 UI표시

스킬 쿨타임 표시

튜토리얼

클릭했다면 해당 기능 수행

 


반환 타입과 맴버 변수가 없는 델리게이트 연습

1.

 //1. 델리게이트 선언
    public delegate void DelOnClick();
    public class Button
    {
        //3-1. 델리게이트 변수 선언
        public DelOnClick onClick;
        //생성자
        public Button() 
        { }
    }
    public void Click() 
    {
        //4. 델리게이트 호출
        Console.WriteLine("유저가 버튼 클릭");
        this.onClick();
    }
public class App
    {
        public App()
        {
            Button btn = new Button();

            //버튼을 눌렀다면 알려줘
            //3-2.델리게이트 인스턴스화
            btn.onClick = this.OnClickButton;

            //유저가 버튼을 누름
            btn.Click();
        }
        //2. 델리게이트에 연결할 메서드 정의
        public void OnClickButton() 
        {
            // 설정 팝업을 연다.
            Console.WriteLine("팝업이 뜬다.");
        }
    }

 

2.

//1. 델리게이트 선언
    public delegate void DelonBuild();
    public class Building
    {
        //3-1. 델리게이트 변수 선언
        public DelonBuild onComplete;
        //생성자
        public Building() 
        {
        }
        public void Build() 
        {
            Console.WriteLine("건물을 건설합니다.");
        }
    }
public class App
    {
        public App()
        {
            Console.WriteLine("App");
            
            Building building = new Building();
            //3-2. 델리게이트 인스턴스화 
            building.onComplete = this.OnComplete;
            //빌드 시작 
            building.Build();
        }

        //2. 델리게이트에 연결할 메서드 정의
        private void OnComplete()
        {
            Console.WriteLine("빌딩 건설 완료");
        }
    }

 

3.

//1. 델리게이트 선언
    public delegate void DelonOpenComplete();
    public class FileManager
    {
        //3-1. 델리게이트 변수 선언
        public DelonOpenComplete onOpenComplete;
        //생성자
        public FileManager() 
        {
        }
        public void Open(string file) 
        {
            Console.WriteLine("파일을 엽니다.");
        }
    }
public class App
    {
        //생성자 
        public App()
        {
            Console.WriteLine("App");

            FileManager fm = new FileManager();
            //3-2. 델리게이트 인스턴스화
            fm.onOpenComplete = this.OnOpenComplete;
            fm.Open("C:\test.txt");
        }

        //2. 델리게이트에 연결할 메서드 선언
        private void OnOpenComplete()
        {
            Console.WriteLine("유저가 파일을 엽니다.");
        }
    }

 

4. 

public class App
    {
        //생성자 
        public App()
        {
            Console.WriteLine("App");
            SceneManager sm = new SceneManager();
            //델리게이트 인스턴스화 
            sm.onLoaded = this.OnLoaded;
            //메서드 호출 
            sm.LoadScene("Lobby");

        }

        //델리게이트 메서드 정의 
        private void OnLoaded()
        {
            Console.WriteLine("씬 로드 완료");
        }
    }
public delegate void DelOnLoaded();
    public class SceneManager
    {
        public DelOnLoaded onLoaded;
        public SceneManager() 
        {
        }
        public void LoadScene(string load) 
        {
            Console.WriteLine("씬을 불러옵니다.");
        }
    }

5. 

public delegate void DelonEndGame();
    public class GameLauncher
    {
        public DelonEndGame onEndGame;
        public GameLauncher() 
        {
        }
        public void StartGame() 
        {
            Console.WriteLine("게임을 시작합니다.");
        }
    }
public class App
    {
        //생성자 
        public App()
        {
            Console.WriteLine("App");
            GameLauncher launcher = new GameLauncher();
            launcher.onEndGame = this.OnEndGame;
            launcher.StartGame();
        }
        private void OnEndGame()
        {

        }
    }

6. 

public delegate void DelonChange();
    public class Deck
    {
        public DelonChange onChange;
        public Deck() 
        {
        }

        public void Change() 
        {
            Console.WriteLine("덱을 변경합니다.");
        }
    }
public class App
    {
        //생성자 
        public App()
        {
            Console.WriteLine("App");
            Deck changeDeck = new Deck();
            changeDeck.onChange = this.OnChangeDeck;
            changeDeck.Change();
        }
        public void OnChangeDeck() 
        {
            Console.WriteLine("덱 변경 완료");
        }
        
    }

 

 

1. 델리게이트 선언

2. 델리게이트 메서드 정의

3. 델리게이트 인스턴스화

4. 콜백 메서드를 인수로 갖는 메서드 정의

5. 콜백 메서드 호출

 


매개 변수가 있는 델리게이트 호출

 

1.

//1. 델리게이트 선언
    public delegate void DelMoveComple(int id);

    public class Marine
    {
        public int Id { get; private set; }
        //3-1. 델리게이트 변수선언 
        public DelMoveComple moveComplete;

        //생성자 
        public Marine(int id)
        {
            this.Id = id;
        }

        public void Move()
        {
            //4. 델리게이트 호출 
            Console.WriteLine("[Marine] 마린 이동합니다.");
            this.moveComplete(this.Id);
        }
    }
public class App
    {
        //생성자 
        public App()
        {
            Console.WriteLine("App");
            Marine marine = new Marine(1234567);
            marine.moveComplete = this.MoveComplete;
            marine.Move();
        }
        public void MoveComplete(int id) 
        {
            Console.WriteLine("마린 ({0})이 앞으로 이동 완료", id);
        }
    }

2. Action 대리자 타입

public class Zealot
    {
        private float x;
        private float y;
        public Action<float, float> onMoveComplete;
        public Zealot(float x, float y) 
        {
            this.x = x;
            this.y = y;
        }
        public void Die(Action callback) 
        {
            callback();
        }
        public void Move(float x, float y) 
        {
            this.x = x;
            this.y = y;

            this.onMoveComplete(this.x, this.y);
        }
    }
public class App
    {
        //생성자 
        public App()
        {
            Console.WriteLine("App");
            Zealot zealot = new Zealot(0,0);
            zealot.onMoveComplete = this.OnMoveComplete;
            zealot.Move(1, 0);
            zealot.Die(OnDie); //대리자에 대해 재사용 가능성이 없을떄 콜백을 많이 사용
            
        }
        private void OnDie() 
        {
            Console.WriteLine("질럿이 죽었습니다.");
        }
        private void OnMoveComplete(float x, float y) 
        {
            Console.WriteLine("질럿 이동완료: {0},{1}", x, y);
        }
    }

 

3. 

//대리자 선언
    public delegate void OnBake();
    public class Oven
    {
        //대리자 변수 선언
        public OnBake onBake;
        public Oven() 
        { }

        public void Bake(Pizza pizza) 
        {
            Console.WriteLine("피자 굽기 시작");
            System.Threading.Thread.Sleep(1000); //1초
            //완료 콜백
            this.onBake();
        }
    }
public class App
    {
        //생성자 
        public App()
        {
            Oven oven = new Oven();
            oven.onBake = this.OnBake;
            oven.Bake(new Pizza());
        }
        private void OnBake() 
        {
            Console.WriteLine("피자가 다 구워졌습니다.");
        }
    }

 

-건설

-건설 완료시 경험치를 줌

 

건물

- 완료 시간

- 완료 대리자

 

Building b = new Building();

b.onComplete = OnCompleteBuilding;

this.Build(b);

 

private void Build(Buiding b){

b.StartBuildProcess(); }

 

private void OnCompleteBuilding()

{ //빌드 완료 경험치 줌

}

 //1. 델리게이트 선언
    public delegate void OnCompleteBuilding();
    public class Building
    {
        //3-1. 델리게이트 변수 선언
        public OnCompleteBuilding onComplete;
        //생성자
        public Building() 
        {
        }
        public void Build(string name) 
        {
            
        }
        public void StartBuildProcess() 
        {
            Console.WriteLine("건물 건설을 시작합니다.");
            for (int i = 0; i < 10; i++) 
            {
                System.Threading.Thread.Sleep(1000);
                Console.WriteLine("{0}0%", i+1);
            }
            this.onComplete();
        }
    }
public class App
    {
        //생성자 
        public App()
        {
            Building b = new Building();
            b.onComplete = OnCompleteBuilding;
            this.Build(b);
        }
        private void Build(Building b) 
        {
            b.StartBuildProcess();
        }
        private void OnCompleteBuilding() 
        {
            Console.WriteLine("건설 완료!");
        }
    }

 

히어로

공격하다

 

팝업

퀘스트 정보

놀 처치 1/8

..

[완료] 놀 처치 8/8

★★★★★★★★

public class App
    {
        private Hero hero;
        private Popup popup;
        public App() 
        {
            Hero hero = new Hero();
            Popup popup = new Popup();
            popup.Print();
            hero.onAttack = this.OnAttack;
            hero.Attack();
            hero.Attack();
            hero.Attack();
            hero.Attack();
            hero.Attack();
        }
        private void OnAttack()
        {
            Console.WriteLine("놀을 공격합니다.");
            this.popup.UpdateInfo();
        }
    }
public class Hero
    {
        public Action onAttack;
        public Hero() 
        { }
        public void Attack() 
        {
            Console.WriteLine("놀을 처치했습니다.");
            onAttack();
        }
    }
public class Popup
    {
        public int monster = 0;
        public int maxMonster = 8;
        public Popup() 
        { }
        public void Print() 
        {
            Console.WriteLine("{0}/{1}", this.monster, this.maxMonster);
        }
        public void UpdateInfo() 
        {
            this.monster++;
            this.Print();
        }
    }

 

 

 

public class Goblin
    {
        public delegate void OnAttackComplete();
        public OnAttackComplete onAttackComplete;
        public enum eState {
            Idle, Attack
        }
        public Goblin() 
        { }
        public void ChangeState(eState state) 
        {
            switch (state) {
                case eState.Idle:
                    Console.WriteLine("Idle");
                    break;
                case eState.Attack:
                    for (int i = 0; i < 5; i++)
                    {
                        Console.WriteLine("goblin_attack_0{0}", i);
                        System.Threading.Thread.Sleep(500);
                    }
                    this.onAttackComplete();
                    break;
            }
        }
    }
public class App
    {

        private Goblin goblin;
        //생성자 
        public App()
        {
            this.goblin = new Goblin();
            goblin.onAttackComplete = this.OnAttackComplete;
            goblin.ChangeState(Goblin.eState.Idle);
            goblin.ChangeState(Goblin.eState.Attack);

        }
        private void OnAttackComplete() 
        {
            this.goblin.ChangeState(Goblin.eState.Idle);
        }
        
    }