línea de base: ReSharper ha investigado su tipo, y descubrió que TFrom
puede usarse contravariantly y TTo
covariantly. La aceptación del refactor le permitirá usar estos tipos con mayor flexibilidad, como se describe a continuación. Si eso puede ser útil para usted, acéptelo.
Tenga en cuenta, sin embargo, que al aceptar este refactorio, se aplican restricciones sobre cómo utilizar estos tipos en el futuro. Si alguna vez escribe un método que toma TTo
como parámetro, obtendrá un error de compilación, ya que no se pueden leer los tipos coviariant. Y lo mismo para TFrom
: nunca podrá tener un método que devuelva este tipo, o tiene un parámetro out
de este tipo.
que le está diciendo que es TFrom
contravariant, y que TTo
es covariante. Estas características fueron recientemente added to C#
Tipo covarianza significa que un más tipo específico se puede hacer pasar en, mientras contravarianza significa que un menos tipo específico se puede hacer pasar en.
IEnumerable<T>
es un buen ejemplo de Tipo covarianza. Dado que los elementos de un IEnumerable<T>
se sólo lectura, es posible configurarlo para algo más específico:
IEnumerable<object> objects = new List<string>();
Considere lo que podría suceder si (hipotéticamente) se dejen de hacer esto para las colecciones que fueron de lectura/escritura :
List<object> objects = new List<string>();
objects.Add(new Car());
//runtime exception
Para pertenecer covariante, un parámetro genérico debe ser utilizado en una de sólo lectura manera estrictamente ; solo debe escribirse del tipo y nunca leer en (de ahí las palabras clave). Es por eso que el ejemplo IEnumerable<T>
funciona, pero el ejemplo List<T>
no. Por cierto, las matrices hacen covarianza de tipo de soporte (ya que Java, creo), por lo que este mismo tipo de error de tiempo de ejecución es posible con las matrices.
La contravarianza de tipo significa todo lo contrario.Para admitir la contravariancia de tipo, un parámetro genérico debe leerse en solamente, y nunca debe escribirse en. Esto le permite sustituir los tipos menos específicos en
Action<T>
es un ejemplo de tipo contravaince:.
Action<object> objAction = (o => Console.WriteLine(o.ToString()));
Action<string> strAction = objAction;
strAction("Hello");
strAction
se declara a tomar un parámetro de cadena, pero funciona bien si sustituye un tipo de objeto. Se pasará una cadena, pero si el delegado que está configurado para trabajar con ella elige tratarla como un objeto, entonces que así sea. Ningún daño hecho.
Para completar, Func<T>
es el caso inverso de Action<T>
; T
aquí solamente se devuelve, por lo tanto es covariante:
Func<string> strDelegate = () => "Hello";
Func<object> myObjFunc = strDelegate;
object O = myObjFunc();
myObjectFunc
se codifica para devolver un objeto. Si lo configura en algo que devuelve una cadena, entonces, de nuevo, no se hace daño.
gracias, es realmente útil. – mhttk
@mhttk - genial. Me alegro de ayudar –
Probablemente la mejor explicación de co/contravarianza que he leído - ¡gracias! –