English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
La covarianza y la contravarianza nos hacen más flexibles al manejar jerarquías de clases.
Antes de aprender sobre covarianza y contravarianza, vea la siguiente jerarquía de clases:
public class Small { } public class Big: Small { } public class Bigger : Big { }
Basado en el ejemplo de clase anterior, Small es la clase base de Big y Big es la clase base de Bigger. Algo que hay que recordar aquí es que las clases derivadas siempre tendrán más que las clases base, por lo que las clases base son más pequeñas que las clases derivadas.
Ahora, veamos la siguiente inicialización:
Como se muestra anteriormente, la clase base puede contener clases derivadas, pero las clases derivadas no pueden contener la clase base. En otras palabras, un instancia puede aceptar grande incluso si se requiere pequeña, pero no puede aceptar pequeña si se requiere grande.
Ahora, veamos la covarianza y la contravarianza.
La covarianza le permite transmitir tipos derivados que requieren el tipo base. La covarianza es como la varianza de tipos idénticos. La clase base y las clases derivadas se consideran clases del mismo tipo que agregan funcionalidades adicionales al tipo base. Por lo tanto, la covarianza le permite usar clases derivadas en lugar de clases base donde se necesita la clase base (si se necesita una subclase, la regla: se puede aceptar una superclase).
La covarianza se puede aplicar a delegados, genéricos, matrices, interfaces, etc.
La covarianza en los delegados permite que el tipo de retorno del método del delegado sea flexible.
public delegate Small covarDel(Big mc); public class Program { public static Big Method1(Big bg) { Console.WriteLine("Method1"); return new Big(); } public static Small Method2(Big bg) { Console.WriteLine("Method2"); return new Small(); } public static void Main(string[] args) { covarDel del = Method1; Small sm1 = del(new Big()); del = Method2; Small sm2 = del(new Big()); } }
Método1 Método2
Como puede ver en el ejemplo anterior, el delegado espera un tipo de retorno Small (clase base), pero aún podemos asignar Method que retorna Big (clase derivada)1así como Method con la misma firma esperada por el delegado2.
Por lo tanto, la covarianza le permite asignar métodos a delegados que tienen tipos de retorno de menor derivación.
Aplicar Contravarianza (contravarianza) al parámetro. La contravarianza permite asignar parámetros de clase base a métodos de delegados que esperan parámetros de clase derivada.
Continuando con el ejemplo anterior, agregue un Method con un tipo de parámetro diferente al del delegado.3:
delegate Small covarDel(Big mc); class Program { static Big Method1(Big bg) { Console.WriteLine("Method1"); return new Big(); } static Small Method2(Big bg) { Console.WriteLine("Method2"); return new Small(); } static Small Method3(Small sml) { Console.WriteLine("Method3"); return new Small(); } static void Main(string[] args) { covarDel del = Method1; del += Method2; del += Method3; Small sm = del(new Big()); }
Método1 Método2 Método3
Como puede ver, Method3con un parámetro de tipo Small, mientras que el delegado espera un parámetro de tipo Big. Sin embargo, puede asignar Method3junto con el delegado.
También puede usar covarianza y contravarianza de la misma manera que se muestra a continuación.
delegate Small covarDel(Big mc); class Program { static Big Method}}4(Small sml) { Console.WriteLine("Method3"); return new Big(); }; static void Main(string[] args) { covarDel del = Method4; Small sm = del(new Big()); } }
Método4