English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
A covariância e contravariância nos tornam mais flexíveis ao lidar com hierarquias de classes.
Antes de aprender sobre covariância e contravariância, veja a seguinte hierarquia de classes:
public class Small { } public class Big: Small { } public class Bigger : Big { }
De acordo com o exemplo de classe acima, Small é a classe base de Big e Big é a classe base de Bigger. Algo a lembrar aqui é que a classe derivada sempre terá mais coisas do que a classe base, portanto, a classe base é menor do que a classe derivada.
Agora, veja a inicialização a seguir:
Como mostrado acima, a classe base pode conter classes derivadas, mas as classes derivadas não podem conter a classe base. Em outras palavras, um instância mesmo que exigida pequena pode aceitar grande, mas se exigida grande não pode aceitar pequena.
Agora, vamos entender a covariância e contravariância.
A covariância permite que você passe tipos derivados, onde é necessária a tipo base. A covariância é como a variação do mesmo tipo. A classe base e outras classes derivadas são consideradas classes do mesmo tipo que adicionam funcionalidades adicionais ao tipo base. Portanto, a covariância permite que você use classes derivadas onde é necessária a classe base (se necessário o subtipo, a regra: pode aceitar o super tipo).
A covariância pode ser aplicada a delegações, genéricos, arrays, interfaces, etc.
A covariância na delegação permite que o tipo de retorno do método da delegação seja flexível.
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 você vê no exemplo acima, o delegado espera o tipo de retorno Small (classe base), mas ainda podemos atribuir Method que retorna Big (classe derivada)1e Method com a assinatura igual à esperada pelo delegado2.
Portanto, a covariância permite que você atribua métodos a delegações com tipos de retorno de menor derivação.
Aplicar Contravariance (contravariância) aos parâmetros. A contravariância permite atribuir parâmetros de classe base a métodos de delegação que esperam parâmetros de classe derivada.
Continuando com o exemplo anterior, adicione um Method com tipo de parâmetro diferente do 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 você vê, Method3Com parâmetro da classe Small, enquanto o delegado espera parâmetro da classe Big. No entanto, você pode atribuir Method3Usando com delegação.
Você também pode usar covariância e contravariância da mesma forma que mostrado a seguir.
delegar Small covarDel(Big mc); classe Program { static Big Method4(Small sml) { Console.WriteLine("Method3); return new Big(); } static void Main(string[] args) { covarDel del = Method4; Small sm = del(new Big()); } }
Método4