C# 대리자, 이벤트 이해 소개

黄舟
풀어 주다: 2016-12-21 14:54:05
원래의
1038명이 탐색했습니다.

목차

l 소개

l 위임이란

l 이벤트의 이해

l 이벤트 키워드

l ​​마지막으로



소개

C#에서 델리게이트와 이벤트를 배우는 과정에서 그것이 무엇인지, 어떻게 사용하는지 이해하기 위해 많은 글을 읽었습니다. 아래의 전체 이해 과정은 아마도 내가 배운 모든 측면을 마스터해야 할 것입니다:-).

위임이란 무엇인가요?

위임과 이벤트의 두 개념은 완전히 호환됩니다. 대리자는 단순히 함수 포인터입니다. 즉, 주소를 전달하여 함수를 참조할 수 있습니다. 대리자는 인스턴스화할 때 생성자에 대한 매개 변수로 참조 함수를 제공하는 클래스입니다.

각 위임에는 고유한 서명이 있습니다. 예: Delegate int SomeDelegate(string s, bool b); 여기에 언급된 서명은 위임 SomeDelegate에 문자열 및 bool 유형 매개 변수가 있음을 의미합니다. int 유형.

위에서 언급한 내용: 대리자를 인스턴스화할 때 해당 생성자에 대한 매개변수로 참조 함수를 제공합니다. 참고: 참조되는 함수는 대리자와 동일한 시그니처를 가져야 합니다.

다음 함수를 살펴보세요:

PRivate int SomeFunction(string str, bool bln){...}

이 함수를 SomeDelegate의 생성자에 전달할 수 있습니다. 유사한 시그니처를 갖기 때문입니다(다른 Word에서는 동일한 매개변수 유형과 번호를 가지며 동일한 데이터 유형을 반환합니다).

SomeDelegate sd = new SomeDelegate(SomeFunction);

sd는 SomeFunction을 의미합니다. 즉, SomeFunction이 sd에 의해 등록되었다는 의미입니다. . , 기억하세요: SomeFunction이 의미하는 바는 나중에 사용할 것입니다.

이제 대리자를 사용하는 방법을 알아야 합니다. 계속해서 이벤트 여정을 이해하겠습니다...

이벤트 이해

C#에서는 다음과 같이 알고 있습니다.

l 버튼은 클릭하면 클릭 이벤트가 발생하는 클래스입니다.

l 시계(Timer)도 밀리초마다 틱 이벤트가 발생하는 클래스입니다.


다음과 같은 플롯이 있다고 가정하고 예제를 통해 학습해 보겠습니다.

이제 CountTo(int countTo, intreachableNum) 메서드를 갖는 Counter 클래스가 있습니다. which 메소드 표현: 지정된 기간(0~~countTo) 내에서reachableNum이 지정된 시점에 도달하면 NumberReached 이벤트가 트리거됩니다.

대리자 유형 변수인 NumberReached 이벤트도 있습니다. 의미: 이벤트 이름을 지정하는 경우 아래와 같이 이벤트 키워드와 사용할 대리자 유형을 사용하여 선언합니다.

public event NumberReachedEventHandler NumberReached; 위의 문에서 NumberReachedEventHandle은 단지 대리자일 뿐이며 더 정확한 표현은 NumberReachedDelegate입니다. 그러나 Microsoft는 MouseDelegate 또는 PaintDelegate를 이런 방식으로 생각하지 않고 제목이 MouseEventHandler 또는 PaintEventHandler라고 생각합니다. 그래서

NumberReachedEventHandler가 NumberReachedDelegate보다 더 편리한 것 같습니다. 알겠습니다. 계속하겠습니다. 이제 이벤트를 선언하기 전에 다음 형식으로 대리자를 정의해야 합니다.

공개 대리자 void NumberReachedEventHandler(object sender, NumberReachedEventArgs e);

이제 선언된 대리자 NumberReachedEventHandle에는 void 반환 값과 object 및 NumberReachedEventArgs의 두 가지 형식 매개 변수가 있습니다. 섹션 1에서 강조한 것처럼 대리자를 인스턴스화할 때 인수로 전달된 함수도 대리자와 동일한 시그니처를 가져야 합니다.

코드에서 PaintEventArgs 또는 MouseEventArgs를 사용하여 마우스의 이동 위치를 결정했습니까? Paint 이벤트를 트리거한 개체에 Graphics 속성을 사용했습니까? 실제로 사용자에게 데이터를 제공하는 클래스는 모두 System.EventArgs 클래스에서 상속됩니다. 이벤트가 매개 변수를 제공하지 않는 경우 이 클래스는 정의되지 않습니다. 우리의 경우에는 다음 클래스를 통해 예상 시점을 제공합니다.

공용 클래스 NumberReachedEventArgs : EventArgs

{

private int _reached

public NumberReachedEventArgs(int num)

{

this._reached = num;

}

public int ReachedNumber

{

get

{ 🎜> return _reached; >네임스페이스 이벤트

{

공개 대리자 void NumberReachedEventHandler(object sender,

NumberReachedEventArgs e)



// / < ;summary>

/// Counter에 대한 요약 설명

///

공개 클래스

> 공개 이벤트 NumberReachedEventHandler NumberReached;



공개 Counter()

//

                                                  // TODO: 여기에 생성자 로직을 추가합니다

🎜> if( countTo
"); ctr=0;ctr<=countTo;ctr++ )

                                                                        NumberReachedEventArgs e = new NumberReachedEventArgs(

🎜>
OnNumberReached(e);

return; //더 이상 계산하지 마세요

}

                                                                           

{

if(NumberReached != null)

                                                    NumberReached(this, e);//이벤트 발생

       ~            이벤트를 실행하려면 다음 사항에 유의해야 합니다.

l NumberReached(NumberReachedEventHandler 대리자의 인스턴스)를 호출하여 트리거 이벤트를 완료합니다.

NumberReached(this, e); 이런 식으로 등록된 모든 함수를 호출할 수 있습니다.

l NumberReachedEventArgs를 통해 등록된 모든 함수에 대한 이벤트 데이터 제공 e = new NumberReachedEventArgs(reachableNum);

l 위 코드를 읽은 후 다음과 같이 질문할 수 있습니다. 왜 다음 코드 대신 OnNumberReached(NumberReachedEventArgs e) 메서드를 사용하여 NumberReached(this, e)를 호출합니까?

if(ctr ==reachableNum)

{

NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);

//OnNumberReached(e); >
if(NumberReached != null)

{

NumberReached(this, e);//이벤트 발생

}

return ;//더 이상 계산하지 마세요

}

이 질문은 좋은 질문이므로 OnNumberReached 서명을 다시 살펴보겠습니다.

protected virtual void OnNumberReached ( NumberReachedEventArgs e)

① 또한 protected 키워드는 이 클래스에서 상속받은 클래스만 이 클래스의 모든 메서드를 호출할 수 있도록 제한한다는 점을 이해하고 있습니다.

②virtual 키워드는 이 메서드가 상속된 클래스에서 재정의될 수 있음을 나타냅니다.

이 두 가지 사항은 매우 유용합니다. Counter에서 상속되는 클래스를 작성하면 OnNumberReached 메서드를 재정의하여 이벤트가 트리거되기 전에 다른 작업을 수행할 수 있습니다.



protected override void OnNumberReached(NumberReachedEventArgs e)

{

//추가 작업 수행

base.OnNumberReached(e) ;

}

참고: base.OnNumberReached(e)를 호출하지 않으면 이 이벤트가 발생하지 않습니다! 이 방법은 클래스를 상속하고 해당 클래스의 다른 이벤트 중 일부를 제외하려는 경우에 유용합니다.

l 대리자 NumberReachedEventHandler는 클래스 정의 외부, 네임스페이스 내에서 정의되며 모든 클래스에 표시된다는 점에도 유의해야 합니다.

자, 이제 실제로 Counter 클래스를 사용해 볼 차례입니다.



간단한 애플리케이션에는 txtCountTo 및 txtReachable이라는 두 개의 텍스트 상자가 있습니다.




아래는 클릭 이벤트입니다. btnRun의:

private void btnRun_Click(객체 전송자, System.EventArgs e)

                                                                       Text=="")

return

oCounter.CountTo (Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text));

}


Private void OCOUNTER_NUMBERREACHED (Object SENDER, NumberReacheDeventargs E)

{
MESSAGEBOX.show ("Reached:" + E " + E .Reachednumber.tstring ( ); NumberReached += new NumberReachedEventHandler(oCounter_NumberReached); oCounter_NumberReached 메소드의 서명은 다음과 유사합니다. 앞서 언급했습니다.

또한 = 대신 +=를 사용한다는 점에 유의하세요. 이는 대리자가 여러 개체를 참조할 수 있는 특수 개체이기 때문입니다(여기서는 여러 함수를 참조할 수 있음을 의미). 예를 들어 oCounter_NumberReached와 동일한 서명을 가진 또 다른

함수 oCounter_NumberReached2가 있는 경우 두 함수를 모두 참조할 수 있습니다.



oCounter = new Counter()

oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached)

oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached2);

이제 이벤트가 트리거된 후 위의 두 함수가 차례로 호출됩니다.



상황에 따라 NumberReached 이벤트가 발생한 후 oCounter_NumberReached2가 더 이상 호출되지 않도록 하려면 다음과 같이 간단히 작성하면 됩니다. oCounter.NumberReached -= new NumberReachedEventHandler(oCounter_NumberReached2);



마지막으로 참조용 전체 소스 코드를 살펴보겠습니다.


Form1.cs


using System;
System.드로잉 사용;
System.ComponentModel 사용;
System.Windows.Forms 사용
네임스페이스 이벤트;
{
                                                                      컨테이너 구성 요소 = null

공개 Form1()
{
🎜> 구성요소 초기화();

                                                                                                oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached );
oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached2)
.
/ //
protected override void Dispose( bool disposing )
{
if ( 처리 )
{
if (컴포넌트 != null)
                                    comComponents.Dispose();        } 

        Windows Form Designer 생성 코드#region Windows Form Designer 생성 코드 
        /**////

 
        /// Designer 지원을 위한 필수 메서드 - 코드 편집기를 사용하여 이 메서드의 내용을 수정하지 마세요.
        /// 이 메서드의 내용을 수정하지 마세요. 
        ///
 
        private void InitializeComponent() 
        { 
            this.cmdRun = new System.Windows.Forms.Button(); 
            this.txtReachable = new System.Windows.Forms.TextBox(); 
            this.txtCountTo = new System.Windows.Forms.TextBox(); 
            this.label1 = new System.Windows.Forms.Label(); 
            this.label2 = new System.Windows.Forms.Label(); 
            this.btnRemoveDelegate = new System.Windows.Forms.Button(); 
            this.SuspendLayout(); 
           //  
            // cmdRun 
           //  
           this.cmdRun.Location = new System. Drawing.Point(16, 72); 
            this.cmdRun.Name = "cmdRun"; 
            this.cmdRun.Size = new System.드로잉.Size(48, 23); 
            this.cmdRun.TabIndex = 2; 
            this.cmdRun.Text = "실행"; 
            this.cmdRun.Click += new System.EventHandler(this.cmdRun_Click); 
           //  
            // txtReachable 
           // 
            this.txtReachable.Location = new System. Drawing.Point(144, 40); 
            this.txtReachable.Name = "txtReachable"; 
            this.txtReachable.Size = new System.드로잉.Size(56, 20); 
            this.txtReachable.TabIndex = 1; 
            this.txtReachable.Text = ""; 
           //  
            // txtCountTo 
           //  
           this.txtCountTo.Location = new System. Drawing.Point(144, 16); 
            this.txtCountTo.Name = "txtCountTo"; 
            this.txtCountTo.Size = new System.드로잉.Size(56, 20); 
            this.txtCountTo.TabIndex = 0; 
            this.txtCountTo.Text = ""; 
           //  
            // 라벨1 
           // 
           this.label1.AutoSize = true; 
            this.label1.Location = new System.드로잉.Point(16, 16); 
            this.label1.Name = "label1"; 
            this.label1.Size = new System.드로잉.Size(51, 13); 
            this.label1.TabIndex = 3; 
            this.label1.Text = "다음까지 계산"; 
           //  
            // label2 
           // 
           this.label2.AutoSize = true; 
            this.label2.Location = new System.드로잉.Point(16, 40); 
            this.label2.Name = "label2"; 
            this.label2.Size = new System.드로잉.Size(99, 13); 
            this.label2.TabIndex = 4; 
            this.label2.Text = "이 번호에 도달하세요";  // btnremovedelegate this.btnremovedelegate.location = new System.Drawing.point (16, 104); 
            this.btnRemoveDelegate.Name = "btnRemoveDelegate"; 
            this.btnRemoveDelegate.Size = new System.드로잉.Size(168, 23); 
            this.btnRemoveDelegate.TabIndex = 5; 
            this.btnRemoveDelegate.Text = "두 번째 핸들러 제거"; 
            this.btnRemoveDelegate.Click += new System.EventHandler(this.btnRemoveDelegate_Click); 
           //  
            // Form1 
           //  
            this.AutoScaleBaseSize = new System.드로잉.Size(5, 13); 
            this.ClientSize = new System.드로잉.Size(224, 134); 
            this.Controls.AddRange(new System.Windows.Forms.Control[] { 
                                                              이 .btnRemoveDelegate, 
                                                               this.label2, 
                                                                     this.label1,                                                                          this.txtCountTo, 
                                                                this.txtReachable, 
                                                                     this.cmdRun}); 
            this.Name = "Form1"; 
            this.Text = "이벤트"; 
            this.ResumeLayout(false); 

        } 
        #endregion 

        /**////  
        /// 애플리케이션의 기본 진입점입니다. 
        ///
 
        [STAThread] 
        static void Main()  
        { 
            Application.Run(new Form1()); }

Private void btnrun_click (객체 발신자, System.EventArgs e) if (txtCountTo.Text == ""|| txtreachable.Text == ")
                반품; 
            oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text)); 
        } 

        private void oCounter_NumberReached(object sender, NumberReachedEventArgs e) 
        { 
           MessageBox.Show("도달: " + e.ReachedNumber.ToString()) ; 
        } 
        private void oCounter_NumberReached2(객체 전송자, NumberReachedEventArgs e) 
        { 
           MessageBox.Show("Reached2: " + e.ReachedNumber.ToString()); 
        } 

        private void btnRemoveDelegate_Click(object sender, System.EventArgs e) 
       { 
           oCounter.NumberReached -= new NumberReachedEventHandler(oCounter_N umberReached2); 
            oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text)); 
        } 
    } 

  






Counter.cs 


  

시스템 사용; 

네임스페이스 이벤트 

    공개 위임 void NumberReachedEventHandler(object sender, NumberReachedEventArgs e); 

    /**////  
    /// 카운터에 대한 요약 설명입니다. 
    ///  
    공개 클래스 카운터 
    { 
        공개 이벤트 NumberReachedEventHandler NumberReached; 
        
        공개 카운터() 
        { 
           //
            // TODO: 여기에 생성자 로직 추가 
            // 
        } 
        public void CountTo(int countTo, int reachableNum) 
        { 
            if(countTo                throw new ArgumentException("reachableNum은 countTo보다 작아야 합니다."); 
            for(int ctr=0;ctr<=countTo;ctr++) 
            { 
              if(ctr ==reachableNum) 
              { 
                   NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum); 
                   OnNumberReached(e); 
                   반환;//더 이상 계산하지 않음 
               } 
           } 
        } 

        보호된 가상 공백 OnNumberReached(NumberReachedEventArgs e) 
        { 
            if(NumberReached! =null) 
            { 
               NumberReached(this, e); 
           } 
        } 
    } 

    공개 클래스 NumberReachedEventArgs : EventArgs 
    { 
        private int _reached; 
        공개 NumberReachedEventArgs(int num) 
        { 
            this._reached = num; 
        } 
        public int ReachedNumber 
        { 
           get 
           { 
               반환 ; 
           } 
        } 
    } 

 以上就是C#委托,事件理解入门的内容,更多关内容请关注PHP中文网(www.php.cn)!


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿