问题
I have the following code that compiles in .NET Framework version 4.0 and above:
public abstract class MyBase { }
public class MyDerived : MyBase { }
public abstract class MyBaseCollection<T> : IList<T> where T : MyBase
{
protected readonly IList<T> deriveds = new List<T>();
public void Test()
{
// This line works in .NET versions 4.0 and above, but not in versions below.
IEnumerable<MyBase> bases = deriveds;
}
#region IList members with NotImplementedException
// ...
#endregion
}
public class MyDerivedCollection : MyBaseCollection<MyDerived> { }
But in .NET Framework below 4.0 I get a compile error on the following line:
IEnumerable<MyBase> bases = deriveds;
Cannot implicitly convert type 'System.Collections.Generic.IList<T>' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?)
Question is what has changed (or was introduced) in .NET 4.0 regarding this?
Is there any documentation about this?
回答1:
In .Net 4.0 the IEnumerable<T>
interface was changed from:
public interface IEnumerable<T>
To
public interface IEnumerable<out T>
Notice that the word out has been added to the generic type parameter. This means that the generic parameter is co-variant which means you can pass in a more derived type.
Covariance Enables you to use a more derived type than originally specified. You can assign an instance of IEnumerable (IEnumerable(Of Derived) in Visual Basic) to a variable of type IEnumerable
See msdn for more information
回答2:
It's about covariance and contravariance of collections. Check the following link to get more information.
Starting with the .NET Framework 4, several generic interfaces have covariant type parameters; for example: IEnumerable, IEnumerator, IQueryable, and IGrouping. All the type parameters of these interfaces are covariant, so the type parameters are used only for the return types of the members.
来源:https://stackoverflow.com/questions/42225616/derived-list-to-base-ienumerable