이벤트-명명 규칙 및 스타일
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
호출하는 대신 메서드 에서 호출 하는 것을 고려하십시오 .Tick
StartTick
OnTick(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
'ProgramingTip' 카테고리의 다른 글
Docker의 HyperKit에서 생성 한 VM에 액세스하는 방법은 무엇입니까? (0) | 2020.12.10 |
---|---|
Sequel Pro 및 MySQL 연결 실패 (0) | 2020.12.10 |
Python에서 시스템의 존재 정보를 얻었습니까? (0) | 2020.12.10 |
jQuery를 사용하여 특정 CSS가있는 모든 요소 선택 (0) | 2020.12.10 |
jQuery를 사용하여 전체 HTML 노드를 어떻게 교체합니까? (0) | 2020.12.10 |