varianza positiva finanzas definicion covarianza correlacion calculadora c# generics covariance

positiva - ¿Es esto un error de covarianza en C#4?



varianza y covarianza definicion (2)

En el siguiente fragmento de código, esperaba poder convertir implícitamente elements en elements baseElements porque TBase es implícitamente convertible a IBase .

public interface IBase { } public interface IDerived : IBase { } public class VarianceBug { public void Foo<TBase>() where TBase : IBase { IEnumerable<TBase> elements = null; IEnumerable<IDerived> derivedElements = null; IEnumerable<IBase> baseElements; // works fine baseElements = derivedElements; // error CS0266: Cannot implicitly convert type // ''System.Collections.Generic.IEnumerable<TBase>'' to // ''System.Collections.Generic.IEnumerable<IBase>''. // An explicit conversion exists (are you missing a cast?) baseElements = elements; } }

Sin embargo, obtengo el error que se menciona en el comentario.

Citando de la especificación:

Un tipo T<A1, …, An> es convertible en varianza a un tipo T<B1, …, Bn> si T es una interfaz o un tipo de delegado declarado con los parámetros de tipo de variante T<X1, …, Xn> , y para cada parámetro de tipo de variante Xi se cumple una de las siguientes condiciones:

  • Xi es covariante y existe una referencia implícita o conversión de identidad de Ai a Bi

  • Xi es contravariante y existe una referencia implícita o conversión de identidad de Bi a Ai

  • Xi es invariante y existe una conversión de identidad de Ai a Bi

Comprobando mi código, parece ser consistente con la especificación:

  • IEnumerable<out T> es un tipo de interfaz

  • IEnumerable<out T> se declara con parámetros de tipo de variante

  • T es covariante

  • existe una conversión de referencia implícita de TBase a IBase

Entonces, ¿es un error en el compilador C # 4?


La varianza solo funciona para tipos de referencia (o hay una conversión de identidad ). No se sabe que TBase es un tipo de referencia, a menos que agregue : class :

public void Foo<TBase>() where TBase : class, IBase

ya que podría escribir un:

public struct Evil : IBase {}


Marc tiene razón, estaba a punto de pegar la misma respuesta.

Vea las Preguntas Frecuentes de Covarianza y Contravarianza:

http://blogs.msdn.com/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx

De las preguntas frecuentes:

"La varianza solo se admite si un parámetro de tipo es un tipo de referencia".

La varianza no es compatible con los tipos de valores

Lo siguiente no compila tampoco:

// int is a value type, so the code doesn''t compile. IEnumerable<Object> objects = new List<int>(); // Compiler error here.