2010-07-26 10 views
5

En el CLR a través de C# tercera edición hay un ejemplo que me parece que no puede hacer sentido de:de diferencia el y co-varianza - CLR a través de C#

Significado invariante que ese parámetro tipo genérico no se puede cambiar . I ha mostrado solo los parámetros de tipo genérico invariable hasta ahora en este capítulo. n

Contravariant Lo que significa que el parámetro de tipo genérico puede cambiar de una clase a una clase derivada de ella. En C#, usted indica contravariante parámetros genéricos con en la palabra clave.

Los parámetros de tipo genérico contravariante pueden aparecer solo en las posiciones de entrada , como por ejemplo el argumento de un método. n Covariante Significa que el argumento de tipo genérico puede cambiar de una clase a una de sus clases base. En C#, usted indica covariante parámetros genéricos con la palabra clave. Los parámetros del tipo genérico covariante pueden aparecer solo en las posiciones de salida como como tipo de devolución del método.

El autor pasa luego a dar este ejemplo:

public delegate TResult Func<in T, out TResult>(T arg); 

En este caso, el parámetro de tipo genérico T es marcado con la palabra clave en, por lo que es contravariant; y el tipo genérico de parámetro TResult está marcado con el cabo de palabras clave, por lo que es covariante

Aquí es donde me encuentro con el problema de la página siguiente (292) A continuación pasa al decir lo contrario cuando se utiliza una interfaz.

Al utilizar delegados que toman argumentos genéricos y valores de retorno, se recomienda a siempre especifique los dentro y fuera palabras clave para contravarianza y covarianza siempre> posible, como hacer esto no tiene ningún efecto negativo y permite a su delegado ser utilizado en más escenarios. Al igual que los delegados, una interfaz con parámetros de tipo genérico puede tener sus parámetros de tipo ser contravariante o covariante. Aquí está un ejemplo de una interfaz con una contravariant> genérico parámetro Tipo:

public interface IEnumerator<out T> : IEnumerator { 
Boolean MoveNext(); 
T Current { get; } 
} 

Como T es contravariante, es posible tener la siguiente compilación de código y ejecución> éxito:

// This method accepts an IEnumerable of any reference type 
Int32 Count(IEnumerable<Object> collection) { ... } 
... 
// The call below passes an IEnumerable<String> to Count 
Int32 c = Count(new[] { "Grant" }); 

En el segundo ejemplo utiliza la palabra clave de salida (IEnumerator<out T>) y luego la llama contravariante. ¿Es correcto o me falta algo?¿Hay alguna diferencia que defina una covariante & contravariante en una interfaz? I have been to Oreilly's website regarding this book and this is not listed.

+0

Es importante tener en cuenta que el diseño de 'Delegate.Combine' es fundamentalmente incompatible con la varianza. Si una rutina tiene un campo inicialmente nulo de tipo delegado 'Acción ', e intenta 'Combinar' con una' Acción ', el campo de tipo' Acción 'tendrá una referencia a' Acción ' . Si uno intenta 'Combinar' eso con 'Acción ', el intento fallará. Por esta razón, los tipos de delegados que se pueden usar con 'Combine' no deben ser covariantes ni contravariantes. Es una lástima que los tipos de delegados no definan sus propios métodos 'Combine', ya que ... – supercat

+0

... un método' Acción .Combine' podría haber tomado con seguridad 'Acción ' y convertirlo a un tipo 'Acción ', sabiendo que el resultado de tal conversión solo sería utilizado por un código que lo alimentaría con un' Cat'. – supercat

Respuesta

20

out = covariante y in = contravariant.

Cualquier palabra que indique lo contrario es un error en mi libro que corregiré en una futura edición.

+6

Wow, bienvenido a SO, Jeffrey! –

+8

Sabes que acabas de registrarte en la versión para desarrolladores del Hotel California, ¿verdad? –

+0

Champán rosado en hielo, ¿alguien? –

8

Eso es un error. Definitivamente es un ejemplo de covarianza. No hay diferencia en el significado de la covarianza y la contradicción entre los delegados y las interfaces.

Le sugiero que envíe un correo electrónico a O'Reilly para informar el error.

+1

O el autor vendrá y responderá directamente ... ':)' – jjnguy

+1

@Justin: Bueno, sí, eso siempre es una opción;) –

Cuestiones relacionadas