Pergunta

Qual é o significado dos conceitos 'covariância' e 'contravariance'?

Dado 2 classes, Animal e Elephant (que herda de Animal ), o meu entendimento é que você teria um erros em tempo de execução se você tentar colocar um elefante em uma matriz de animais, e isso acontece porque Elephant é "maior" (mais específico) do animal. Mas você poderia colocar um animal em uma matriz de elefante, vendo como Elephant é garantida para conter as propriedades animal?

Foi útil?

Solução

Você tem isso para trás. Você pode adicionar um elefante para uma matriz animal porque é um Animal, e está garantido para ter todos os métodos de um animal é obrigado a ter. Você não pode adicionar um animal para uma matriz do elefante, porque ele faz não tem todos os métodos que um elefante é obrigado a ter.

O artigo da Wikipedia sobre covariância e contravariance tem uma boa explicação para isso:

Dentro do sistema tipo de uma linguagem de programação, um operador de tipos de tipos é covariant se ele preserva a ordenação, =, de tipos, que ordena tipos de mais aqueles específicos para os mais genéricos; é contravariante se inverte essa ordem. Se nenhuma destas situações se aplica, o operador é invariável. Estes termos vêm de teoria das categorias.

Além disso, você disse que tipo de elefante era "maior", e este não é o caso. Tipo de animal é "maior" no sentido de que ele inclui tipos mais específicos, tais como o elefante, girafa, e Leão.

Outras dicas

Tenha um olhar para este panorama de covariância e contravariance em C # 4.0 e ver se isso ajuda:

http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx

Você deve tentar ler páginas 45-49 de Introducing .NET 4.0 com Visual Studio 2010 que lida com este exemplo exato. Ele ainda tem algumas boas fotos de elefantes.

O principal ponto de tirar é, para fazer isso

var things = new List<IThing<IContent>> { new ConcreteThing() }

com:

public class ConcreteThing : IThing<ConcreteContent>
{

}

é necessário o "out" na definição de interface, o que permitirá formas mais específicas a ser definido, mas nada lido fora do IThing deve ser garantido para ser o tipo mais geral.

public interface IThing<out T> where T : IContent
{
}

enter descrição da imagem aqui

public interface IGoOut<out T>
{
    T Func();
}
public interface IComeIn<in T>
{
    void Action(T obj);
}
public class GoOutClass<T>:IGoOut<T>
{
    public T Func()
    {
        return default(T);
    }
}

public class ComeInClass<T> : IComeIn<T>
{
    public void Action(T obj) {  }
}

==========================================================
object obj = null;
//Covariance Example [Array +  IEnumerable<T> +  IEnumerator<T>  +  IInterface<Out T>  +  Func<T>]
object[] array = (string[]) obj;
IEnumerable<object> enumerable = (IEnumerable<string>) obj;
IEnumerator<object> enumerator = (IEnumerator<string>)obj;
IGoOut<object> goOut = (GoOutClass<string>)obj;
Func<object> func = (Func<string>)obj;


//Contravariance Example[IInterface<in T>]
IComeIn<string> comeIn = (ComeInClass<object>) obj;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top