C#

4.델리게이트,이벤트,애트리뷰트

J개발자 2020. 9. 18. 13:51

델리게이트

델리게이트(c++)에서는 제공하지 않는 기능

메서드를 대신하여 호출 받아 델리게이트에 있는 메서드를 대신 호출

메소드를 캡슐화하기 때문에 더 효율적(안전)

c++과c의 함수 포인터와 유사하지만 더 객체지향적이고 타입이 안정적이다.

주로 스레드와 이벤트 처리하는데 사용된다.

 

선언형식은 일반 메서드 선언과 유사

[변경자]delegate 반환형 델리게이트_이름(인자_리스트);

 

public -다른클래스 참조

internal-같은 프로그램 내 참조

1.메서드 선정

2.메서드에 맞게(반환형,인자리스트) 델리게이트 선언

3.델리게이트할 메서드를 갖는 객체 생성

4.델리게이트를 생성하고 호출

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _4강
{
    delegate void SimpleDelegate1(); //델리게이트 선언
    delegate void SimpleDelegate2(int i);  //델리게이트 선언
    class MyClass {  //델리게이트 할 메서드를 갖고 있는 클래스
        public void MyMethod1()       //메서드 선정
        {
            System.Console.WriteLine("MyMethod1");

        }
        public void MyMethod2(int x)    //메서드 선정
        {
            System.Console.WriteLine("MyMethod2 x=" + x);
        }
    }

    class Program
    {
       
        static void Main(string[] args)
        {
            MyClass at = new MyClass();   //선정 메서드 포함된 클래스의 객체 생성
            SimpleDelegate1 d1 = new SimpleDelegate1(at.MyMethod1); //SimpleDelegate d1 = at.MyMethod1;
            SimpleDelegate2 d2 = new SimpleDelegate2(at.MyMethod2);
            d1();
            d2(1000);
        }
    }
}

멀티 델리게이트 

"+="  델리게이트에 다른 델리게이트 추가

"-="   여러 개가 묶인 델리게이트에서 특정 델리게이트를 제거 ->연결된 모든 메서드 전부 호출 가능

         But! C#에서는 반환형이 다른 것을 지원하지 않아 멀티 델리게이트 사용시 메서드의 반환형은 void로 .

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MultiDelagate { }
delegate void TopDelegator(string str); //델리게이트 선언
class Top    
{ 
    public static void StaticMethod(string str)  //델리게이트할 정적 메서드 
    {
        Console.Write("정적 메서드 입니다.\t");
        Console.WriteLine(str + "\r\n");

    }
    public void NormalMethod(string str)
    {
        Console.Write("일반 메서드 입니다.\t");
        Console.WriteLine(str + "\r\n");
    }
}
    class program
{
    public static void Main()
    {
        Top t = new Top();
        TopDelegator td1 = new TopDelegator(t.NormalMethod);    //델리게이트 생성(참조변수.메서드)
        TopDelegator td2 = new TopDelegator(Top.StaticMethod);  //델리게이트 생성(클래스이름.메서드)정적일때!
        td1("topDelegator 1을 추가");
        td1 += td2;
        td1("topDelegator 2을 추가");
        td1 -= td2;
        td1("topDelegator 2를 제거");
    }
}

콘솔 결과

이벤트

어떤 동작에 의해 발생하는 사건

이벤트가 발생하면 이벤트에 등록된 메서드를 통해 응답된다. 주로 운영체제에 의해 발생되며, 발생된 이벤트를 해당 애플리케이션에 전달된다. 

[변경자]event DelegateType EventName;

new,static,virtal

이벤트는 델리게이트 객체와 같이 정의되어 사용된다(이벤트를 구현하기 위해 델리게이트를 사용)

public delegate voud MyDelegate();//델리게이트 선언

private event MyDelegate ExamEvent;//이벤트 선언

 

1.이벤트가 발생시 처리해 줄 메서드(이벤트 처리기)작성

2.이벤트 처리기의 형태와 일치하는 델리게이트 선언

3.이벤트 선언(미리 선언된 이벤트는 생략)

4.이벤트에 이벤트 처리기 등록

5.이벤트 생성

 ExamEvent라는 이벤트가 발생하면 MyDelegate 라는 델리게이트를 호출한다.따라서 델리게이트에 이벤트 처리기를 등록!

ExampleClass obj = new ExampleClass(); //이벤트 처리기(Method)를 갖는 객첼를 생성

ExamEvent +=new MyDelegate(obj.Method);//이벤트에 이벤트 처리기를 등록

 

using EventTest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EventTest
{
    public delegate void MyEventHandler();  //델리게이트 선언
}
class Button 
{
    public event MyEventHandler Push;   //이벤트 선언
    public void OnPush()
    {
        if (Push != null) Push();     //이벤트 발생
    }
}
class EventHandlerClass             //이벤트 처리기를 갖는 클래스
{
    public void MyHandler()          //이벤트 처리기
    {
        Console.WriteLine("이벤트 처리기를 수행합니다. ");

    }
}
class programe
{
    public static void Main()
    {
        Button btn = new Button();        //이벤트를 발생시키는 객체
        EventHandlerClass ob = new EventHandlerClass();  //이벤트 처리기 갖는 객체
        btn.Push += new MyEventHandler(ob.MyHandler);  //btn.Push += ob.MyHandler
        btn.OnPush();
    }
    
}

System.EventHandler 델리게이트  <-이미 선언된 이것을 사용하거나 파생 클래스를 이벤트로 사용하는 것이 더 효율적!

public delgate void EventHandler(odject sender, EventArgs args)

//sender는 이벤트를 보내는 객체,System.EventArgs(이를 상속받은 클래스)는 이벤트 관련 정보를 제공.

 

 

애트리뷰트(attribute)

런타임 때 프로그래밍 단위(어셈블리,클래스,필드,메서트,프로퍼티)에 메타 정보를 추가 및 변경하기 위해 사용

[attribute 애트리뷰트이름("위치인자(필수)",이름인자 = value,...)]

표준, 사용자 정의 ,직렬화 애트리뷰트가 있음.

using System.Dignostics;  <-표준 애트리뷰트 사용시 꼭 작성

 

Conditional 애트리뷰트: 조건부 메서드를 작성할 때(호출,수행결정)  #define

 

Obsolete 애트리뷰트:앞으로 사용되지 않을 메서드 표시할 때(위치 인자에 경고 메시지작성)

#define KOREA   //위치인자 KOREA정의
using System;
using System.Diagnostics;

namespace CondObsAttrTest
{
    class Program
    {
        [Conditional("KOREA")]
        public static void KoreaMethod(){  //KOREA가 정의되어 있으므로 컴파일 됨.
            Console.WriteLine("KOREA...");
        }
        [Conditional("JAPAN")]
        public static void JapanMethod(){   //정의되어 있지 않아 컴파일 안됨.
            Console.WriteLine("JAPAN...");  
        }
        
        [Obsolete(" 경고, Obsolete method...")]   //컴파일 때 경고 메시지를 출력
        public static void ObsoleteMethod(){  
            Console.WriteLine("Obsolete method...");
        }
        public static void Main(){
            Program.KoreaMethod();
            Program.JapanMethod();
            Program.ObsoleteMethod();
        }
    }

사용자 정의 애트리뷰트

클래스의 정의가 필요하다 따라서 System.Attribute클래스를 상속해야 하며 클래스 이름은 ___Attribute형태여야함.

정의한 애트리뷰트 사용할 때는 ____만 사용하면 된다.



using System;
using System.Diagnostics;

    namespace UserAttrTest
    {
        public class UserAttribute : Attribute  //사용자 정의 애트리뷰트User//애트리뷰트 클래스 상속
        {
            private string message;       //멤버변수생성
            public UserAttribute(string msg)  //생성자(멤버 변수의 메시지 값을 생성)
            {
                this.message = msg;
            }
            public string Message  //프로퍼티(메시지 값을 읽음)
            {
                get{return message;}
            }

            [User("사용자 정의 애트리뷰트")]
            class program
            {
                public static void Main()
                {
                    Type type = typeof(program);
                    object[] arr = type.GetCustomAttributes(typeof(UserAttribute), true);
                    if (arr.Length == 0)
                        Console.WriteLine(" No Custom attributes");
                    else
                    {
                        UserAttribute ua = (UserAttribute)arr[0];
                        Console.WriteLine(ua.Message);
                    }
                }
            }
        }
    }

'C#' 카테고리의 다른 글

직렬화,역직렬화  (0) 2020.12.05
C# OpenFileDialog 사용하기  (0) 2020.12.04
C# 파일과 디렉토리  (0) 2020.12.03
C# richtextbox를 이용한 예제(복사,붙여넣기,바꾸기)  (0) 2020.12.03