2009-07-21 7 views
13

Entiendo los beneficios de utilizar la firma de delegado del controlador de eventos MS estándar, ya que le permite expandir fácilmente la información transmitida a través del evento sin romper las relaciones antiguas que se basan en la antigua firma de delegado.¿Qué tan malo es crear un delegado controlador de eventos sin la firma estándar (Obj sender, EventArgs args)?

Lo que me pregunto es en la práctica con qué frecuencia las personas siguen esta regla? Decir que tengo un evento simple como esto

public event NameChangedHandler NameChanged; 
public delegate void NameChangedHandler(Object sender, string oldName, string newName); 

Es un evento simple, y estoy casi seguro de que los únicos argumentos que jamás voy a necesitar saber del evento NameChanged es el objeto cuyo nombre cambiado, el nombre antiguo y el nuevo nombre. Entonces, ¿vale la pena crear una clase separada NameChangedEventArgs, o para eventos simples como este, es aceptable simplemente devolver los argumentos directamente a través de los argumentos delegados?

Respuesta

6

Se puede hacer todo el camino equivocado si usted es el único que tiene que tratar con él. Pero no es una mala idea aprender estándares y apegarse a ellos para que pueda mantener buenos hábitos cuando está trabajando en el código con otros.

Así que le haremos un trato. Si prometes hacerlo de la manera correcta, te daré un fragmento de código que lo hará mucho menos doloroso. Sólo hay que poner esto en un archivo .snippet, y poner ese archivo en:

Mis documentos \ Visual Studio 2008 \ fragmentos de código \ Visual C# \ Mis fragmentos de código \
(o Visual Studio 2005 si es aplicable)

Y aquí está el fragmento; utilizarlo en VS escribiendo ev2Generic y golpear Tab:

<?xml version="1.0" encoding="utf-8" ?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
    <Header> 
     <Title>Generic event with two types/arguments.</Title> 
     <Shortcut>ev2Generic</Shortcut> 
     <Description>Code snippet for event handler and On method</Description> 
     <Author>Kyralessa</Author> 
     <SnippetTypes> 
     <SnippetType>Expansion</SnippetType> 
     </SnippetTypes> 
    </Header> 
    <Snippet> 
     <Declarations> 
     <Literal> 
      <ID>type1</ID> 
      <ToolTip>Type of the first property in the EventArgs subclass.</ToolTip> 
      <Default>propertyType1</Default> 
     </Literal> 
     <Literal> 
      <ID>arg1Name</ID> 
      <ToolTip>Name of the first argument in the EventArgs subclass constructor.</ToolTip> 
      <Default>property1Name</Default> 
     </Literal> 
     <Literal> 
      <ID>property1Name</ID> 
      <ToolTip>Name of the first property in the EventArgs subclass.</ToolTip> 
      <Default>Property1Name</Default> 
     </Literal> 
     <Literal> 
      <ID>type2</ID> 
      <ToolTip>Type of the second property in the EventArgs subclass.</ToolTip> 
      <Default>propertyType2</Default> 
     </Literal> 
     <Literal> 
      <ID>arg2Name</ID> 
      <ToolTip>Name of the second argument in the EventArgs subclass constructor.</ToolTip> 
      <Default>property2Name</Default> 
     </Literal> 
     <Literal> 
      <ID>property2Name</ID> 
      <ToolTip>Name of the second property in the EventArgs subclass.</ToolTip> 
      <Default>Property2Name</Default> 
     </Literal> 
     <Literal> 
      <ID>eventName</ID> 
      <ToolTip>Name of the event</ToolTip> 
      <Default>NameOfEvent</Default> 
     </Literal> 
     </Declarations> 
     <Code Language="CSharp"> 
     <![CDATA[public class $eventName$EventArgs : System.EventArgs 
     { 
     public $eventName$EventArgs($type1$ $arg1Name$, $type2$ $arg2Name$) 
     { 
      this.$property1Name$ = $arg1Name$; 
      this.$property2Name$ = $arg2Name$; 
     } 

     public $type1$ $property1Name$ { get; private set; } 
     public $type2$ $property2Name$ { get; private set; } 
     } 

     public event EventHandler<$eventName$EventArgs> $eventName$; 
      protected virtual void On$eventName$($eventName$EventArgs e) 
      { 
       var handler = $eventName$; 
       if (handler != null) 
        handler(this, e); 
      }]]> 
     </Code> 
    </Snippet> 
    </CodeSnippet> 
</CodeSnippets> 
+0

Puede adaptar esto, por supuesto, para tener una sola propiedad, o tres, o tantas como desee. Tengo fragmentos para 1, 2 o 3 propiedades, así como para el caso simple de crear un evento sin datos de eventos específicos. –

+0

Soy consciente de que esta es una respuesta anterior, pero me gustaría agregar un enlace a este hilo: [Firma de evento en .NET - ¿Usando un 'Remitente' de tipo fuerte?] (Http://stackoverflow.com/q/ 1046016/69809). En mi humilde opinión, no hay ninguna razón para seguir dogmáticamente una convención, si resulta en prácticas de codificación malolientes (por ejemplo, emitir el parámetro 'sender'). La clase 'EventArgs' tampoco proporciona ningún beneficio, aunque * podría * argumentar que es mejor ajustar los datos pasados ​​para mantener la compatibilidad de la fuente. – Groo

+0

@Groo, es una idea interesante. No había visto ese hilo antes. Tenga en cuenta que la persona que hizo la pregunta * aquí * estaba hablando sobre el uso de un delegado controlador de eventos con más de dos propiedades, y no está utilizando el patrón 'sender, EventArgs' estándar. Lo que estaba en cuestión aquí no era tanto el 'remitente' de transmisión, sino también si se usaba o no un parámetro' EventArgs' o 'EventArgs ' en lugar de múltiples parámetros. –

10

Utilice los delegados genéricos EventHandler<T> para sus eventos y cree un tipo derivado de EventArgs para guardar los datos de su evento. Entonces en otras palabras, siempre. Es algo que siempre sabes exactamente cómo funciona cuando te encuentras con él porque de otra manera nunca se hace.

Editar:

análisis de código CA1003: Use generic event handler instances
análisis de código CA1009: Declare event handlers correctly

+0

No sé por qué estabas echado abajo –

+2

Eh, sucede. :) Realmente lo odio cuando no hay explicación. –

+0

+1 Solo se responde explícitamente a EventHandler

4

En la práctica, ¿con qué frecuencia [clases no EventArgs uso de derivados] personas.

Nunca he encontrado un momento en que las clases derivadas de EventArgs no se hayan utilizado. Como dices tú mismo, aumenta tu capacidad de cambiar tu código más tarde. También argumentaría que la legibilidad ha mejorado, ya que es fácil ver que este es un controlador de eventos.

¿Vale la pena crear una clase NameChangedEventArgs separado, o para eventos simples como este es que aceptable para simplemente devolver los argumentos directamente a través de los argumentos delegado?

Parece que dice que usará EventArgs para controladores de eventos con más parámetros y no lo usará en instancias como esta. Honestamente, eso simplemente no es una opción cuando se programa en C#.La consistencia es imprescindible, especialmente en el mundo actual de foros como este, proyectos de código abierto, etc. donde es fácil perderlo. Claro que si estás programando esto debajo de una roca, puedes hacer lo que quieras, pero la gran comunidad de C# te agradecerá por seguir los estándares y especialmente por usar consistencia en tu código.

+0

Sí, esa era realmente mi pregunta. Si se trata de un evento complejo, entiendo por qué querría tener flexibilidad con el uso de EventArgs. Pero si es algo simple en el que puedo estar 99% seguro de que sé todos los argumentos que voy a necesitar, no estaba seguro si realmente importaba crear una clase EventArgs separada con uno o dos argumentos. –

Cuestiones relacionadas