代码之家  ›  专栏  ›  技术社区  ›  Matt Whitfield

为什么采用IEnumerable<interface>的函数不接受IEnumerable<class>?

  •  5
  • Matt Whitfield  · 技术社区  · 16 年前

    比如说,我有一门课:

    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,因此可以将MyFoo的IEnumerable视为IMYBAR的IEnumerable。一个平凡的现实世界的例子是,生产一个汽车清单,然后被告知它不是一个汽车清单。

    这只是一个小小的烦恼,但如果有人能对此有所了解,我将非常感激。

    4 回复  |  直到 16 年前
        1
  •  14
  •   Mehrdad Afshari    16 年前

    这将在C 4.0中工作!你所说的叫做 一般协方差 .

    同时,您可以使用 Cast extension method :

    List<IMyBar> interfaceList = new List<IMyBar>(classList.Cast<IMyBar>());
    
        2
  •  3
  •   John Buchanan    16 年前

    这在.NET 4.0中受支持,但不早于.NET 4.0。

    http://msdn.microsoft.com/en-us/library/dd799517%28VS.100%29.aspx

        3
  •  3
  •   Joel Coehoorn    16 年前

    澄清一下,它现在不起作用的原因是 IEnumerable<MyClass> 不从继承 IEnumerable<MyBar> . 我再说一次:派生类型的可枚举不从基类型的可枚举继承。相反,这两种类型都专门针对 IEnumerable<T> 泛型类型。在.NET 3.5及更低版本中,它们除了专门化(不是继承)之外没有其他关系,否则在类型系统中是两种完全不同的类型。

    .NET 4.0根本不会更改这些类型的关联方式。它们仍然是两种完全不同的类型,只通过专门化来联系。它将要做的是允许您编写了解专门化关系的方法,并且在某些情况下允许您在编写另一个方法时替换一个方法。

        4
  •  1
  •   Community Mohan Dere    9 年前

    如果您想在IEnumerable(如您在问题标题中所写)和列表(如您在问题中所写)之间进行强制转换,可以等待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
    
    推荐文章