Resharper has suggested to change from
interface IModelMapper<TFrom, TTo>
{
TTo Map(TFrom input);
}
into
interface IModelMapper<in TFrom, out TTo>
So I investigate a little and ended reading this article (found through a Wikipedia article) and some more Google.
I am still not sure what this would imply for my application so I am tempted of not accepting the suggestion. What would are the benefits this change would introduce and I am not considering by ignoring the suggestion?
More explicitly, why should I accept it?
Bottom Line: Resharper has investigated your type, and discovered that
TFrommay be used contravariantly, andTTocovariantly. Accepting the refactor would allow you to use these types with greater flexibility, as described below. If that might be of value to you, accept it.Note, however, that accepting this refactor would place restrictions on how you use these types in the future. If you ever write a method that takes
TToas a parameter, you’ll get a compiler error, since coviariant types cannot be read in. And ditto forTFrom: you’ll never be able to have a method that returns this type, or has anoutparameter of this type.That’s telling you that
TFromis contravariant, and thatTTois covariant. These were features recently added to C#Type covariance means that a more specific type may be passed in, while contravariance means that a less specific type may be passed in.
IEnumerable<T>is a good example of type covariance. Since items in anIEnumerable<T>are read only, you may set it to something more specific:Consider what could happen if (hypothetically) you were allowed to do this for collections that were read/write:
To be type covariant, a generic parameter must be used in a strictly read-only manner; it must only ever be written out from the type, and never read in (hence the keywords). That’s why the
IEnumerable<T>example works, but theList<T>example doesn’t. By the way, arrays do support type covariance (since Java does, I believe), and so this same kind of runtime error is possible with arrays.Type contravariance means the opposite. To support type contravariance a generic parameter must be read in only, and never written out. This allows you to substitute less specific types in.
Action<T>is an example of type contravaince:strActionis declared to take a string parameter, but it works fine if you substitute an object type. A string will be passed in, but if the delegate it’s set to work with chooses to treat it as an object, then so be it. No harm done.For completeness,
Func<T>is the inverse case ofAction<T>; hereTis only returned, therefore it’s covariant:myObjectFuncis coded to return an object. If you set it to something that returns a string, then, again, no harm done.