pseudocodigo programacion practicas para notacion nomenclatura indentación hungara estándares convención codigos c# events delegates

c# - programacion - Eventos: convención y estilo de nomenclatura



practicas de programacion en c# (7)

Estoy aprendiendo sobre Eventos / Delegados en C #. ¿Podría preguntar su opinión sobre el estilo de nomenclatura / codificación que he elegido (tomado del libro de Head First C #)?

Le estoy enseñando a un amigo sobre esto mañana, y estoy tratando de encontrar la forma más elegante de explicar los conceptos. (¡pensé que la mejor manera de entender un tema es tratar de enseñarlo!)

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"); } }

El código nb se refactoriza desde http://www.codeproject.com/KB/cs/simplesteventexample.aspx


Diría que la mejor guía para eventos en general, incluidas las convenciones de nombres, está here .

Es la convención que he adoptado, brevemente:

  • Los nombres de eventos normalmente terminan con un final de verbo con -ing o -ed (Cerrado / Cerrado, Cargando / Cargado)
  • La clase que declara el evento debe tener un virtual protegido en [EventName] que debe ser utilizado por el resto de la clase para generar el evento. Este método también puede ser utilizado por subclases para plantear el evento, y también sobrecargado para modificar la lógica de generación de eventos.
  • A menudo hay confusión sobre el uso de ''Handler'': por coherencia, todos los delegados deben ser postfijados con Handler, tratar de evitar llamar a los métodos que implementan los Handlers ''handlers''
  • La convención de nomenclatura de VS predeterminada para el método que implementa el controlador es EventPublisherName_EventName.

En tu caso, podría ser:

class Metronome { event Action Ticked; internalMethod() { // bla bla Ticked(); } }

Por encima del uso de la base por debajo de la convención, autodescriptivo;]

Fuente de eventos:

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); } }

Por cierto. el event palabra clave es opcional pero permite distinguir "eventos" de "devoluciones de llamada"

Oyente de eventos:

class AlarmManager { // pattern: NotifyXxx public NotifyLockStateChanged(bool state) { // ... } // pattern: [as above] public NotifyOpened(bool opened) { // OR public NotifyDoorOpened(bool opened) { // ... } }

Y vinculante [el código parece humano amigable]

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

Incluso el envío manual de eventos es "legible por humanos".

alarmManager.NotifyDoorOpened(true);

A veces, más expresivo puede ser "verbo + ing"

dataGenerator.DataWaiting += dataGenerator.NotifyDataWaiting;

Cualquiera sea la convención que elija, sea consecuente con ella.



Hay algunos puntos que mencionaría:

Metronome.OnTick no parece nombrarse correctamente. Semánticamente, "OnTick" me dice que se llamará cuando marque "Tic", pero eso no es realmente lo que está sucediendo. Yo lo llamaría "ir" en su lugar.

El modelo generalmente aceptado, sin embargo, sería hacer lo siguiente. OnTick es un método virtual que plantea el evento. De esta forma, puede anular fácilmente el comportamiento predeterminado en clases heredadas y llamar a la base para plantear el evento.

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 } } }

Además, sé que este es un ejemplo simple, pero si no hay oyentes conectados, su código arrojará en Tick(this, EventArgs.Empty) . Al menos debe incluir un guardia nulo para verificar si hay oyentes:

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

Sin embargo, esto aún es vulnerable en un entorno multiproceso si el oyente no está registrado entre el guardia y la invocación. Lo mejor sería capturar primero a los oyentes actuales y llamarlos:

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

Sé que esta es una respuesta antigua, pero como todavía está recabando votaciones, esta es la forma de hacer las cosas C # 6. El concepto de "guardia" puede ser reemplazado por una llamada de método condicional y el compilador hace lo correcto (TM) con respecto a la captura de los oyentes:

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


Microsoft ha escrito un extenso conjunto de directrices de nomenclatura y lo colocó en la biblioteca de MSDN. Puede encontrar los artículos aquí: Pautas para los nombres

Además de las pautas generales de uso de mayúsculas, aquí está lo que tiene para ''Eventos'' en la página Nombres de Tipo Miembros :

Nombra eventos con un verbo o una frase verbal.

Proporcione a los nombres de los eventos un concepto de antes y después, utilizando el presente y el pasado. Por ejemplo, un evento cercano que se genera antes de que se cierre una ventana se llamaría Cierre y uno que se genera después de cerrar la ventana se llamaría Cerrado.

No use los prefijos o sufijos Antes o Después para indicar eventos previos y posteriores.

Nombra manejadores de eventos (delegados usados ​​como tipos de eventos) con el sufijo EventHandler.

Utilice dos parámetros denominados sender y e en las firmas del controlador de eventos.

El parámetro del remitente debe ser del tipo Object, y el parámetro e debe ser una instancia de heredar de EventArgs.

Nombra las clases de argumento de evento con el sufijo EventArgs.


Se ve bien, aparte del hecho de que OnTick no sigue el modelo típico de invocación de eventos. Normalmente, On[EventName] plantea el evento una sola vez, como

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

Considere crear este método y OnTick nombre de su método " StartTick " StartTick " StartTick ", y en lugar de invocar Tick directamente desde StartTick , llame a OnTick(EventArgs.Empty) desde el método StartTick .


Un punto que he encontrado después de usar eventos en .Net durante muchos años es la necesidad repetitiva de verificar el evento para un controlador nulo en cada invocación. Todavía tengo que ver un código en vivo que haga cualquier cosa, pero no llame al evento si es nulo.

Lo que comencé a hacer es poner un manejador falso en cada evento que creo para salvar la necesidad de hacer la comprobación nula.

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. } }