Pergunta

Eu estou tentando descobrir o significado exato da Covariance palavras e Contravariance de vários artigos on-line e perguntas sobre StackOverflow, e pelo que posso entender, é só uma outra palavra para o polimorfismo .

Am I corrigir com a declaração acima? Ou ter eu entendi errado?

Foi útil?

Solução

É certamente relacionada com polimorfismo. Eu não diria que eles são apenas "mais uma palavra" para o polimorfismo embora -. Eles são sobre situações muito específicas, onde você pode tratar um tipo como se fosse um outro tipo em um determinado contexto

Por exemplo, com o polimorfismo normal, você pode tratar qualquer referência a um Banana como uma referência a uma Fruit - mas isso não significa que você pode substituir Fruit todas vez que você vê o tipo Banana. Por exemplo, um List<Banana> não pode ser tratado como um List<Fruit> porque list.Add(new Apple()) é válido para List<Fruit> mas não para List<Banana>.

covariância permite uma "maior" (menos especica) Tipo de ser substituído em uma API onde o tipo original é única utilizado numa posição "saída" (por exemplo, como um valor de retorno). Contravariância permite um (mais específico) tipo "menor" a ser substituído em uma API onde o tipo original é única utilizado numa posição "de entrada".

É difícil entrar em todos os detalhes em um único post SO (embora esperemos que alguém vai fazer um trabalho melhor do que isso!). Eric Lippert tem um excelente href="https://blogs.msdn.microsoft.com/ericlippert/tag/covariance-and-contravariance/" de posts sobre isso.

Outras dicas

Obrigado por todas as shout-saídas, pessoal.

respostas

de Jon e Rasmus são bons, gostaria apenas de acrescentar uma nota técnica rápida.

Ao falar casualmente e informalmente, sim, as pessoas usam "covariância" e "contravariance" para se referir a um tipo específico de polimorfismo. Ou seja, o tipo de polimorfismo, onde você tratar uma seqüência de aranhas como se fosse uma seqüência de animais.

Se fôssemos para obter todos os computadores-sciency e tentar fazer definições mais técnicas, então eu provavelmente não diria que covariância e contravariance são "um tipo de polimorfismo". Gostaria de abordar uma definição mais técnica como esta:

Em primeiro lugar, eu notar que existem dois tipos possíveis de polimorfismo em C # que você pode estar falando, e é importante não confundi-los.

O primeiro tipo é tradicionalmente chamado de "polimorfismo ad hoc", e isso é o polimorfismo onde você tem um método M (Animal X), e você passar aranhas e girafas e wallabies a ele, e o método uniformemente trata seu passado-in argumentos da mesma forma, utilizando os pontos comuns garantidos pela classe base animal.

O segundo tipo é tradicionalmente chamado de "polimorfismo paramétrico", ou "polimorfismo genérico". Essa é a capacidade de fazer um método M<T>(T t) genérica e, em seguida, ter um monte de código no método que mais uma vez, trata o argumento uniformemente com base em semelhanças garantidos pelos constrangimentos ao T.

Eu acho que você está falando sobre o primeiro tipo de polimorfismo. Mas meu ponto é apenas que podemos definir polimorfismo como a capacidade de uma linguagem de programação para coisas diferentes tratar uniformemente com base em uma comunalidade conhecido. (Por exemplo, um tipo de base conhecida, ou conhecida interface implementada.)

Covariância e contravariance é a capacidade de uma linguagem de programação para aproveitam comuns entre tipos genéricos deduzidas comuns conhecidas de seus argumentos de tipo.

Você pode pensar em co- e contravariance como sendo uma forma avançada de polimorfismo. Não apenas você pode usar uma classe criança como se fosse seu pai-classe, com co- e contravariance, o polimorfismo se estende a classes que diz respeito às classes polimórficas.

Imagine duas classes:

public class Pet { /*...*/ }
public class Cat:Pet { /*...*/ }

O polimorfismo é ser capaz de usar um Cat como um Pet:

void Feed(Pet pet) { /* ... */ }

Cat cat = ...
Feed(cat);

Co e contravariance é usado para falar sobre a possibilidade de usar um ICollection<Cat> como um ICollection<Pet> (covariância):

void FeedAll(ICollection<Pet> pets) { /* ... */ }

List<Cat> cats = ...
FeedAll(cats);

ou usar um Action<Pet> como um Action<Cat> (contravariance):

Action<Pet> GetFeeder() { /* ... */ }

Action<Cat> feeder = GetFeeder();

Eric Lippert escreveu uma grande série de posts sobre isso quando eles foram os primeiros projetar o recurso. uma parte é aqui .

Eu acho que é é tipo especial de polimorfismo não outra palavra para isso. É o polimorfismo em delegados , onde um delegado com um tipo de retorno de base pode aceitar tipo de criança.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top