将自定义集合转换为已实现的接口
Cast custom collection to implemented interfaces
下面,为什么Todos1可以,而Todos2不行?如何让它发挥作用?
class Program
{
static void Main(string[] args)
{
_todos = new CustomCollection<Todo>();
}
private static CustomCollection<Todo> _todos;
public static IEnumerable<ITodo> Todos1
{
get { return _todos; }
}
public static ICustomCollection<ITodo> Todos2
{
get { return _todos; }
}
public class CustomCollection<T> : Collection<T>, ICustomCollection<T>
{
}
public interface ICustomCollection<T> : IEnumerable<T>
{
}
public interface ITodo
{
}
public class Todo : ITodo
{
public string Description { get; set; }
}
}
方差就是这样运作的; IEnumerable<T>
实际上是IEnumerable<out T>
,意思是协变;这意味着任何 IEnumerable<Todo>
也是 IEnumerable<ITodo>
,因为任何 Todo
都是 ITodo
.
然而,collections / lists / etc not协变(或逆变);所以这里没有隐含的可铸性。原因是:
- 你有一个
CustomCollection<Todo>
- 如果可以转换为
CustomCollection<ITodo>
,你可以 Add
any ITodo
- 包括
class SomethingElse : ITodo
,这是 不是 Todo
- 所以你的 collection 中有一个非
Todo
Todo
编译器在保护你!
您应该将 ICustomCollection<T>
接口声明为 covariant
public interface ICustomCollection<out T> : IEnumerable<T>
{
}
否则它是不变的,您只能将其转换为用于声明的相同 Todo
类型,而不是 ITodo
接口。
IEnumerable<T>
已经具有协变泛型类型参数 T
,因此第一个 属性 按预期工作。
下面,为什么Todos1可以,而Todos2不行?如何让它发挥作用?
class Program
{
static void Main(string[] args)
{
_todos = new CustomCollection<Todo>();
}
private static CustomCollection<Todo> _todos;
public static IEnumerable<ITodo> Todos1
{
get { return _todos; }
}
public static ICustomCollection<ITodo> Todos2
{
get { return _todos; }
}
public class CustomCollection<T> : Collection<T>, ICustomCollection<T>
{
}
public interface ICustomCollection<T> : IEnumerable<T>
{
}
public interface ITodo
{
}
public class Todo : ITodo
{
public string Description { get; set; }
}
}
方差就是这样运作的; IEnumerable<T>
实际上是IEnumerable<out T>
,意思是协变;这意味着任何 IEnumerable<Todo>
也是 IEnumerable<ITodo>
,因为任何 Todo
都是 ITodo
.
然而,collections / lists / etc not协变(或逆变);所以这里没有隐含的可铸性。原因是:
- 你有一个
CustomCollection<Todo>
- 如果可以转换为
CustomCollection<ITodo>
,你可以Add
anyITodo
- 包括
class SomethingElse : ITodo
,这是 不是Todo
- 所以你的 collection 中有一个非
Todo
Todo
编译器在保护你!
您应该将 ICustomCollection<T>
接口声明为 covariant
public interface ICustomCollection<out T> : IEnumerable<T>
{
}
否则它是不变的,您只能将其转换为用于声明的相同 Todo
类型,而不是 ITodo
接口。
IEnumerable<T>
已经具有协变泛型类型参数 T
,因此第一个 属性 按预期工作。