2 added 63 characters in body
source | link

This is mostly a rewording of this excellent blog by Eric Lippert:

C# sub types have always been assignment compatible with their base types e.g. given that Teacher is derived from Person Person p = new Teacher(); is valid i.e. there is a relation isAssignable(x,y) which is true IFF x= y is allowed.

before C# 4 generic collections of sub types were not assignment compatible with generic collections of base types (i.e. List<Teacher>IEnumerable<Teacher> does not derive from List<Person>IEnumerable<Person> so you could not assign List<Teacher>IEnumerable<Teacher> to a List<Person>IEnumerable<Person>) i.e. isAssignable(List<x>IEnumerable<x>,List<y>IEnumerable<y>) was always false regardless of the value of isAssignable(x,y)

C# 4 adds variance for generic types, this allows a generic type to be *variant over a projection from T -> A<T>. which means that for covariant parameters, relations which hold for T,U hold for A<T>,A<U>, and for contra-variant the relation is reversed. i.e. for the relationship isAssignable(x,y) a types that are covariant over the projection like List<>IEnumerable<>s has the same relations as their generic parameters so isAssignable(x,y) == isAssignable(List<x>IEnumerable<x>,List<y>IEnumerable<y>)

This is mostly a rewording of this excellent blog by Eric Lippert:

C# sub types have always been assignment compatible with their base types e.g. given that Teacher is derived from Person Person p = new Teacher(); is valid i.e. there is a relation isAssignable(x,y) which is true IFF x= y is allowed.

before C# 4 generic collections of sub types were not assignment compatible with generic collections of base types (i.e. List<Teacher> does not derive from List<Person> so you could not assign List<Teacher> to a List<Person>) i.e. isAssignable(List<x>,List<y>) was always false regardless of the value of isAssignable(x,y)

C# 4 adds variance for generic types, this allows a generic type to be *variant over a projection from T -> A<T>. which means that for covariant parameters, relations which hold for T,U hold for A<T>,A<U>, and for contra-variant the relation is reversed. i.e. for the relationship isAssignable(x,y) a types that are covariant over the projection like List<>s has the same relations as their generic parameters so isAssignable(x,y) == isAssignable(List<x>,List<y>)

This is mostly a rewording of this excellent blog by Eric Lippert:

C# sub types have always been assignment compatible with their base types e.g. given that Teacher is derived from Person Person p = new Teacher(); is valid i.e. there is a relation isAssignable(x,y) which is true IFF x= y is allowed.

before C# 4 generic collections of sub types were not assignment compatible with generic collections of base types (i.e. IEnumerable<Teacher> does not derive from IEnumerable<Person> so you could not assign IEnumerable<Teacher> to a IEnumerable<Person>) i.e. isAssignable(IEnumerable<x>,IEnumerable<y>) was always false regardless of the value of isAssignable(x,y)

C# 4 adds variance for generic types, this allows a generic type to be *variant over a projection from T -> A<T>. which means that for covariant parameters, relations which hold for T,U hold for A<T>,A<U>, and for contra-variant the relation is reversed. i.e. for the relationship isAssignable(x,y) a types that are covariant over the projection like IEnumerable<>s has the same relations as their generic parameters so isAssignable(x,y) == isAssignable(IEnumerable<x>,IEnumerable<y>)

1
source | link

This is mostly a rewording of this excellent blog by Eric Lippert:

C# sub types have always been assignment compatible with their base types e.g. given that Teacher is derived from Person Person p = new Teacher(); is valid i.e. there is a relation isAssignable(x,y) which is true IFF x= y is allowed.

before C# 4 generic collections of sub types were not assignment compatible with generic collections of base types (i.e. List<Teacher> does not derive from List<Person> so you could not assign List<Teacher> to a List<Person>) i.e. isAssignable(List<x>,List<y>) was always false regardless of the value of isAssignable(x,y)

C# 4 adds variance for generic types, this allows a generic type to be *variant over a projection from T -> A<T>. which means that for covariant parameters, relations which hold for T,U hold for A<T>,A<U>, and for contra-variant the relation is reversed. i.e. for the relationship isAssignable(x,y) a types that are covariant over the projection like List<>s has the same relations as their generic parameters so isAssignable(x,y) == isAssignable(List<x>,List<y>)