ProgramingTip

이벤트-명명 규칙 및 스타일

bestdevel 2020. 12. 10. 20:57
반응형

이벤트-명명 규칙 및 스타일


C #의 이벤트 / 대리자에 대해 배우고 있습니다. 내가 선택한 명명 / 코딩 스타일 (Head First C # 책에서 발췌)에 대한 의견을 물어볼 수 있습니까?

내일 친구에게 이것에 대해 설명하는 가장 우아한 방법을 생각해 내려고 노력하고 있습니다. (주제를 이해하는 가장 좋은 방법은 시도하고있는 것입니다!)

class Program
    {
        static void Main()
        {
            // setup the metronome and make sure the EventHandler delegate is ready
            Metronome metronome = new Metronome();

            // wires up the metronome_Tick method to the EventHandler delegate
            Listener listener = new Listener(metronome);
            metronome.OnTick();
        }
    }

public class Metronome
    {
        // a delegate
        // so every time Tick is called, the runtime calls another method
        // in this case Listener.metronome_Tick
        public event EventHandler Tick;

        public void OnTick()
        {
            while (true)
            {
                Thread.Sleep(2000);
                // because using EventHandler delegate, need to include the sending object and eventargs 
                // although we are not using them
                Tick(this, EventArgs.Empty);
            }
        }
    }

public class Listener
    {
        public Listener(Metronome metronome)
        {
            metronome.Tick += new EventHandler(metronome_Tick);
        }

        private void metronome_Tick(object sender, EventArgs e)
        {
            Console.WriteLine("Heard it");
        }
    }

nb 코드는 http://www.codeproject.com/KB/cs/simplesteventexample.aspx 에서 리팩터링되었습니다 .


제가 언급 할 몇 가지 사항이 있습니다.

Metronome.OnTick의 이름이 지정되지 않을 것입니다. 의미 적으로 "OnTick"은 "Tick"일 때 호출 될 것이 실제로 일어나는 일은 아닙니다. 대신 "Go"라고 부 사용합니다.

그러나 일반적으로 허용되는 모델은 다음을 수행하는 것입니다. OnTick이벤트를 발생시키는 가상 메서드입니다. 이렇게하면 상속 된 클래스의 기본 동작을 쉽게 재정의하고 기본 동작을 호출하여 이벤트를 발생시킵니다.

class Metronome
{
    public event EventHandler Tick;

    protected virtual void OnTick(EventArgs e)
    {
        //Raise the Tick event (see below for an explanation of this)
        var tickEvent = Tick;
        if(tickEvent != null)
            tickEvent(this, e);
    }

    public void Go()
    {
        while(true)
        {
            Thread.Sleep(2000);
            OnTick(EventArgs.Empty); //Raises the Tick event
        }
    }
}

또한 간편한 예라는 것을 알고있을 것 Tick(this, EventArgs.Empty)입니다. 리스너를 선택해야 할 최소한의 널 가드를 포함해야합니다.

if(Tick != null)
    Tick(this, EventArgs.Empty);

그러나 리스너가 가드와 호출 사이에 등록되지 않은 경우 다중적인 환경에서 여전히 취약합니다. 가장 좋은 방법은 먼저 현재 리스너를 활용하고 호출하는 것입니다.

var tickEvent = Tick;
if(tickEvent != null)
    tickEvent(this, EventArgs.Empty);

나는 여전히 오래된 대답이라는 것을 알고 있습니다. 여전히 upvotes를 수집하고 있기 때문에 여기에 C # 6 방법이 있습니다. 전체 "가드"개념은 조건부 메서드 호출로 대체 될 수있는 컴파일러는 실제로 리스너 작업과 관련하여 올바른 작업 (TM)을 수행합니다.

Tick?.Invoke(this, EventArgs.Empty);

Microsoft는 실질적인 지시를 작성하여 MSDN 라이브러리에 넣었습니다. 여기에서 기사를 사용할 수 있습니다. 이름에 대한 지침

일반적인 대문자 사용 지침 외에 유형 구성원의 이름 페이지의 '이벤트'에 대한 내용 다음과 있습니다.

동사 또는 동사 구로 이벤트 이름을 지정합니다.

현재 및 과거 시제를 사용하여 이벤트 이름에 전후 개념을 지정하십시오. 예를 들어, 창이 닫히기 전에 발생라고 닫히는 이벤트를 닫습니다. 닫히고 창이 닫히면 발생하는 이벤트가 닫힙니다.

접두사 또는 접미사를 사용하지 않고 사전 및 사후 이벤트를 나타냅니다.

EventHandler 접미사를 사용하여 이벤트 처리기 (이벤트 유형으로 사용되는 대리인)의 이름을 지정합니다.

이벤트 서명에 보낸 사람 및 e라는 두 개의 매개 변수를 사용하십시오.

발신자 매개 변수는 객체 유형이어야하며, e 매개 변수는 EventArgs의 인스턴스이거나 상속되어야합니다.

EventArgs 접미사를 사용하여 이벤트 인수 클래스의 이름을 지정하십시오.


명명 규칙을 포함하여 일반적으로 이벤트에 대한 가이드는 여기에 있습니다 .

제가 채택한 약속입니다.

  • 이벤트 이름은 일반적으로 -ing 또는 -ed (Closing / Closed, Loading / Loaded)로 끝나는 동사로 종료됩니다.
  • 이벤트를 선언하는 클래스에는 이벤트 발생을 위해 나머지 클래스에서 사용해야하는 보호 된 가상 On [EventName]이 있어야합니다. 이 메서드는 하위 클래스에서 이벤트를 발생시키는 데 사용할 수도 있고 오버로드하여 이벤트 발생 논리를 수정할 수도 있습니다.
  • 'Handler'사용에 대해 종종 혼동이 있습니다. 일관성을 위해 모든 대리자는 Handler로 접미사를 붙여야합니다. Handler 'handlers'를 구현하는 메서드를 호출하지 않도록하십시오.
  • 핸들러를 구현하는 메서드의 기본 VS 명명 규칙은 EventPublisherName_EventName입니다.

Microsoft가 Visual Studio에서 생성 한 이벤트 처리기 이름을 사용하여 자체 명명 규칙을 위반하는 방식에 대해 흥미 롭습니다.

참조 : 이벤트 이름 지정 지침 (.NET Framework 1.1)


수년 동안 .Net에서 이벤트를 사용한 후 찾은 요점은 모든 호출에서 null 처리기에 대한 이벤트를 반복적으로 확인해야한다는 것입니다. 나는 아직 아무것도하지 않고 이벤트가 null 인 경우 호출하지 않는 라이브 코드를 보지 못했습니다.

내가 시작한 것은 null 검사를 수행 할 필요성을 줄이기 위해 내가 만드는 모든 이벤트에 더미 핸들러를 배치하는 것입니다.

public class Metronome
{
    public event EventHandler Tick =+ (s,e) => {};

    protected virtual void OnTick(EventArgs e)
    {
        Tick(this, e);  // now it's safe to call without the null check.
    }
}

OnTick일반적인 이벤트 호출 모델을 따르지 않는다는 사실을 제외하면 좋아 보입니다 . 일반적으로 다음과 On[EventName]같이 이벤트를 한 번만 발생시킵니다.

protected virtual void OnTick(EventArgs e)
{
    if(Tick != null) Tick(this, e);
}

이 메서드를 만들고 기존 " OnTick"메서드의 이름을 " "로 바꾸고 에서 직접 StartTick호출하는 대신 메서드 에서 호출 하는 것을 고려하십시오 .TickStartTickOnTick(EventArgs.Empty)StartTick


귀하의 경우에는 다음과 같을 수 있습니다.

class Metronome {
  event Action Ticked;

  internalMethod() {
    // bla bla
    Ticked();
  }
}

관례 아래의 sampple 사용, 자체 설명;]

이벤트 소스 :

class Door {

  // case1: property change, pattern: xxxChanged
  public event Action<bool> LockStateChanged;

  // case2: pure action, pattern: "past verb"
  public event Action<bool> Opened;

  internalMethodGeneratingEvents() {
    // bla bla ...

    Opened(true);
    LockStateChanged(false);
  }

}

BTW. 키워드 event는 선택 사항이지만 '이벤트'와 '콜백'을 구분할 수 있습니다.

이벤트 리스너 :

class AlarmManager {

  // pattern: NotifyXxx
  public NotifyLockStateChanged(bool state) {
    // ...
  }

  // pattern: [as above]      
  public NotifyOpened(bool opened) {
  // OR
  public NotifyDoorOpened(bool opened) {
    // ...
  }

}

그리고 바인딩 [코드는 인간에게 친숙해 보입니다]

door.LockStateChanged += alarmManager.NotifyLockStateChanged;
door.Moved += alarmManager.NotifyDoorOpened;

수동으로 이벤트를 보내는 경우에도 "사람이 읽을 수 있습니다".

alarmManager.NotifyDoorOpened(true);

때로는 더 표현력이 "동사 + ing"일 수 있습니다.

dataGenerator.DataWaiting += dataGenerator.NotifyDataWaiting;

어떤 규칙을 선택하든 일관성을 유지하십시오.

참고 URL : https://stackoverflow.com/questions/724085/events-naming-convention-and-style

반응형