2011-02-09 9 views
13

Cuando escribo eventos públicos para mis objetos comerciales, he adaptado el hábito de siempre pasar la instancia como "emisor como Objeto", además de parámetros específicos adicionales. Me acabo de preguntar ahora ¿por qué no estoy especificando la clase?parámetro de evento; "remitente como Objeto", o "remitente como T"?

Así que para usted con más experiencia; ¿Alguna vez aprobó la clase distinta como remitente en un evento? Y si es así, ¿cuáles son sus criterios de decisión para cuando esto está bien/no está bien?

+0

Si tiene que preguntar "¿por qué no?", Realmente no debería hacerlo. Las pautas sobre cómo crear firmas de eventos fueron diseñadas como si fueran por una razón. Al menos lee por esas razones antes de decidir desviarse de ellas solo porque puedes. –

+0

Piénselo: ¿qué pasaría si luego considera que su evento se ajusta a otro lugar y desea plantearlo desde otro punto de su código? ¿Sería la misma clase de remitente? No si especifica el tipo de remitente ... – Smur

+1

@Lasse: podría preguntar "¿por qué?".No sabía que era una guía para esto, no soy un programador. Sin embargo, como hay una guía, me gustaría saber si es común o muy raro romper esta directriz o no. – bretddog

Respuesta

11

No seas extremo. EventHandler(object sender, EventArgs e) tiene un remitente de objeto para que podamos usarlo en muchas circunstancias. Pero eso no significa que un emisor fuertemente tipado sea malo. Un remitente fuertemente tipado es útil cuando este delegado no va a ser ampliamente utilizado (como EventHandler) p.

public delegate void SaveHandler(Controller sender, EventArgs e); 

Ahora otros desarrolladores (o alguien que use su biblioteca) pueden recogonize que el remitente tienen que ser un Controller, y ellos estarán contentos de no codificar así:

public void MySaveHandler(object sender, EventArgs arg) 
{ 
    var controller = sender as Controller; 
    if (controller != null) 
    { 
     //do something 
    } 
    else 
    { 
     //throw an exception at runtime? 
     //It can be avoided if sender is strongly-typed 
    } 
} 

Y usted incluso puede hacerlo genérico:

public delegate void SaveHandler<T>(T sender, EventArgs args) 
               where T: IController; 

Es puramente legal y buena práctica en C#. Debe aclarar lo que quiere hacer y luego elegir la mejor manera. Cualquiera de ellos es malo/malo.

1

No hay tal restricción. Es solo una guía que se sigue a lo largo de BCL (Base Class Library) y otros marcos populares.

Le recomendaría que lo siga para mantener la coherencia si va a ser utilizado por otros desarrolladores o se lanzará como un marco.

5

Hay un design guideline que especifica que un controlador de eventos debe tener dos params: remitente (un Objeto) y e (EventArgs o derivado de eso).

+1

+1: Personalmente considero el mejor consejo aquí. Las pautas no son reglas o leyes. Usted * puede * desviarse de ellos, pero antes de hacerlo debe saber realmente por qué se crearon en primer lugar, qué tipo de problemas o situaciones tratan de manejar y cuáles son sus alternativas. Desviarse solo porque puede nunca es una buena razón. –

+1

@Lasse: en realidad, dudo que hubiera una razón válida (o al menos "suficientemente buena") por la que optaron por esto, excepto que no había genéricos en la primera versión de .NET. – Groo

+0

@Groo: Parece que recuerdo haber leído en uno de los blogs de MSDN hace un tiempo que esta es exactamente la razón por la que se tomó la decisión de diseño para tener el parámetro del remitente escrito como un objeto. Solo una de esas cosas que ahora se ha convertido en una convención tan bien establecida que la gente espera en las API públicas. Absolutamente no hay ninguna razón por la cual el parámetro no deba escribirse de manera fuerte o genérica si no está expuesto públicamente. – 0b101010

1

Por lo que yo veo, puede crear delegados con los parámetros que desee y luego crear un evento utilizando ese delegado y luego puede invocar el evento y pasar los parámetros o puede usar el argumento de evento personalizado como se muestra here . Como la otra respuesta sugiere. Mantenlo constante.

en realidad no responde a su pregunta acerca de los criterios de decisión, pero creo que sirve

1

Mi filosofía actual es mantener las prácticas de código lo más cerca posible de la manera estándar de Microsoft como sea posible. Usted consigue dos cosas de esto:

  • nuevos desarrolladores pueden entender rápidamente su código
  • se entrena a los desarrolladores existentes cómo el resto del marco funciona
0

no es un obligatorio para que usted pueda tener tal implementación. Normalmente se realiza debido a que el delegado EventHandler se diseñó con dicho prototipo.

Es un simple guideline seguido a través de la Biblioteca de clases base. Pero seguro que puedes hacerte tus propios Parámetros e implementaciones.

Pero recuerde que si va a ser utilizado por algún desarrollador que no sea usted, deberá conocer dicha implementación. Su don para el bien común y la flexibilidad de utilizar un evento en cualquier lugar independientemente de la clase de su utiliza en.

Si se define una personalizada Prototipo para el evento entonces yo sugeriría que también se define personalizada Delegado que se asegurará de que se tener una excepción si no se pasa el tipo apropiado.(Usuario tendrá que hacer una conversión explícita si es necesario)

De esta manera:

public delegate void MyEventHandler(MyType sender, EventArgs e); 

luego usarlo cuando sea necesario como:

this.MyEvent += new MyEventHandler(my_eventhandlerfunction); 
1

Es una buena práctica usar la firma object sender, EventArgs e, como el método puede manejar cualquier evento de esa firma. Por ejemplo, en un proyecto que utiliza un control de gráficos, existen varios tipos de eventos MouseOver, de un DataSeries, de la Leyenda, de todo el lienzo.

De esta manera, puede manejar cualquier fuente del evento, ya que la mayoría de las veces, la información está en el EventArgs.

Además, no tiene que enviar el remitente al pasarlo al delegado, ya que cualquier instancia de clase es un objeto en el fondo.

+3

No creo que esto sea relevante. El código del cliente aún podría manejar el evento a través de un método con el remitente escrito como 'objeto', incluso si el evento se declara con un remitente con más caracteres. [Contravariance] (http://stackoverflow.com/questions/1046016/event-signature-in-net-using-a-strong-typed-sender). – MarkJ

1

Hubo mucha discusión sobre una pregunta relacionada en StackOverflow hace algún tiempo. Aquí está la pregunta: Event Signature in .NET -- Using a strong-typed sender

Finalmente, todo se reduce a la preferencia. En la mayoría de los casos, le gustaría que los manejadores de su evento estén vinculados a un tipo de clase particular, por lo que hacer que el remitente sea un objeto y luego regresar a la clase para obtener acceso a sus propiedades puede no ir bien con usted [ tampoco me cae bien].

Además, con .NET 3+ y la introducción de la covarianza y la contravarianza del delegado, no debería ser un problema utilizar un delegado fuertemente tipado. Debo admitir que he usado manipuladores de eventos fuertemente tipados más de una vez en mi código.

Como dije antes, se trata de preferencia; Microsoft acaba de emitir un conjunto de guía líneas no reglas ...

Cuestiones relacionadas