2010-11-02 23 views
10

que estaba leyendo acerca de la acción Delegado en MSDN y por lo que esta debajo de la sintaxisAcción <T> o Acción <in T>?

public delegate void Action<in T>(T obj); 

De lo que miraba en c-sharpcorner.com y utilicé esta sintaxis

public delegate void Action<T>(T obj); 

Como se puede ver que no hay in antes T.
¿Qué sintaxis es la correcta y qué significa eso in?
EDITAR: la misma sintaxis utilizada para Predicate.

Gracias.

Respuesta

9

La parte in es para covariance and contravariance y se introdujo en .NET 4.0, el artículo al que se enlazó se publicó en 2006 antes de que se lanzara .NET 4.0 (por lo tanto, obviamente no se refiere a la varianza co ntra).

10

in y out (contravarianza genérico y covarianza) solamente se introdujeron en C# 4, y los delegados e interfaces fueron modificados para .NET 4 - así en Action<T> NET 3.5 se convirtió Action<in T> en NET 4.

El El artículo al que se refiere es de 2006, mucho antes de que apareciera .NET 4.

Si cambia qué versión de MSDN está visualizando, verá el cambio; por ejemplo, .NET 3.5 version lo muestra sin in.

0

Vale la pena señalar que conceptualmente todos los tipos de delegados podrían ser intrínsecamente covariantes con cualquier parámetro de tipo utilizado únicamente como tipo de retorno y contravariante con respecto a los parámetros de tipo utilizados solo para parámetros de método pasados ​​por valor y los compiladores podrían automáticamente permitir tal variación, excepto por un problema: mientras que la declaración in de Action evitará que el compilador grazne si se pasa un Action<Animal> a un método que espera un Action<Cat>, algunos métodos que esperan un Action<Cat> pueden comportarse muy mal si se les da un Action<Animal>. En general, los métodos que solo deben aceptar delegados de tipos con especificadores de covarianza/contravarianza si funcionan correctamente con todos los delegados; de lo contrario, deberían aceptar tipos de delegados sin dichos especificadores.

La mayoría de métodos que aceptar una Action<Cat> funcionará bien con un Action<Animal>, por lo que Microsoft decidió con carácter retroactivo para hacer Action<T> contravariante. Debido a que muchos métodos que aceptan EventHandler<T> pueden fallar muy gravemente si se les da algo que no coincide perfectamente con el tipo esperado, EventHandler<T> no se hizo contravariante.

En retrospectiva, si cada tipo de delegado hubiera definido su propio método Combine, habría sido posible hacer que la covarianza de delegado y la contravarianza funcionen en casi todos los casos. Si CatEventArgs:AnimalEventArgs, diciendo

EventHandler<CatEventArgs> myEvents=null; 
void AddEvent(EventHandler<CatEventArgs> newEvent) 
{ 
    myEvents = EventHandler<CatEventArgs>.Combine(myEvents, newEvent); 
} 

podrían haber resultado un pasado-en EventHandler<AnimalEventsArgs> en un EventHandler<CatEventArgs>, que entonces podrían combinarse con cualquier otro delegado que igualmente se podría convertir en un EventHandler<CatEventArgs>.Desafortunadamente, dado que Combine solo se definió en Delegate, no hay forma de que el método Combine sepa qué tipo de delegado necesita el código de llamada [En mi humilde opinión, incluso sin covarianza/contravarianza, hubiera sido agradable que los delegados definieran su propio Combine y Remove métodos, ya que eso habría evitado la necesidad de encasillar el resultado de Delegate.Combine].

Cuestiones relacionadas