比方说,我有一个班级:
public class MyFoo : IMyBar
{
...
}
然后,我想使用以下代码:
List<MyFoo> classList = new List<MyFoo>();
classList.Add(new MyFoo(1));
classList.Add(new MyFoo(2));
classList.Add(new MyFoo(3));
List<IMyBar> interfaceList = new List<IMyBar>(classList);
但这会产生错误:
`Argument '1': cannot convert from 'IEnumerable<MyFoo>' to 'IEnumerable<IMyBar>'
这是为什么?由于MyFoo实现了IMyBar,人们可以预期IEnumerable的MyFoo可以被视为IMyBar的IEnumerable。一个世俗的现实世界的例子是生产汽车列表,然后被告知它不是车辆列表。
这只是一个小小的烦恼,但如果有人能够对此有所了解,我会非常感激。
答案 0 :(得分:14)
这将在C#4.0中运行!你所说的是泛型协方差。
在此期间,您可以使用Cast
extension method:
List<IMyBar> interfaceList = new List<IMyBar>(classList.Cast<IMyBar>());
答案 1 :(得分:3)
这在.NET 4.0中受支持,但不是更早。
http://msdn.microsoft.com/en-us/library/dd799517%28VS.100%29.aspx
答案 2 :(得分:3)
澄清一下,它现在不起作用的原因是IEnumerable<MyClass>
不会从IEnumerable<MyBar>
继承。我再说一遍:派生类型的可枚举不会从基类型的可枚举继承。相反,两种类型都专门化IEnumerable<T>
泛型类型。在.Net 3.5及更低版本中,它们除了特化之外没有其他关系(不是继承),在类型系统中是两种完全不同的类型。
.Net 4.0不会改变这些类型的相关方式。它们仍然是两种完全不同的类型,只能通过专业化来实现。它的作用是允许你编写了解专业化关系的方法,在某些情况下允许你在编写另一个时替换一个。
答案 3 :(得分:1)
如果你想在IEnumerables(正如你在问题的标题中所写)之间而不是在列表之间(如你在问题中所写的那样)之间进行投射,你可以等待c#4.0协方差特征。 在那之前,您可以使用扩展方法。 但是我不会使用其他答案中提到的Cast extension method,而是编写我自己的方法,它只能用于IEnumerable中的协方差转换。何时/如果您切换到C#4.0,您将很容易找到代码中转换为冗余的所有位置。
public static class cEnumerableExtensions
{
public static IEnumerable<TResult> CovarianceConversion<TResult, TSource>(this IEnumerable<TSource> source)
where TSource : TResult
{
foreach (var item in source)
{
yield return item;
}
}
}
最终节点。似乎有no precompiler constant for the netframework 4.0,否则我会添加
#if DOTNET4
[Obsolete("You can directly cast in C# 4.0.")]
#endif