多个IEnumerable实现悖论

时间:2013-07-15 11:15:47

标签: c# inheritance ienumerable

  1. 我有一个通用类A< T >,它实现了IEnumerable< T [] >。
  2. 我想要一个继承自A< char >的便利包装器B.并实现IEnumerable< string >。

    public class A<T> : IEnumerable<T[]>
    {
        public IEnumerator<T[]> GetEnumerator()
        {
            return Enumerate().GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    
        protected IEnumerable<T[]> Enumerate()
        {
            throw new System.NotImplementedException();
        }
    }
    
    public class B : A<char>, IEnumerable<string>
    {
        public IEnumerator<string> GetEnumerator()
        {
            return Enumerate().Select(s => new string(s)).GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    
  3. 现在,这完全正常,foreach变量类型被推断为字符串:

    B b = new B();
    foreach (var s in b)
    {
        string[] split = s.Split(' ');
    }
    

    但这不会编译,说“无法从使用中推断出类型参数,请尝试明确指定类型参数”:

    string[] strings = b.ToArray();
    

    然而,这有效:

    string[] strings = b.ToArray<string>();
    

    任何人都可以解释这种编译器行为吗?

    显然,B实现了IEnumerable&lt; char [] &gt;和IEnumerable&lt; string &gt;并且它可能无法弄清楚我想要调用哪一个,但为什么它在“foreach”样本中工作正常?

    请不要建议我通过作文来解决我的问题 - 这是我的最后手段。

2 个答案:

答案 0 :(得分:2)

foreach循环不使用IEnumerableIEnumerable<T>实现。即使您的班级没有实施任何一个,您也可以使用foreach。它唯一需要的是GetEnumerator方法,它返回IEnumerator实现。

请检查此问题:How is foreach implemented in C#?

这就是为什么您的班级使用foreach而不使用ToArray()

答案 1 :(得分:2)

不同之处如下:

foreach实际上会查找名为GetEnumerator的公共方法。它并不真正关心IEnumerable<T>。您的班级B只有一个名为GetEnumerator的公共方法:B中定义的隐藏 A中定义的方法。

另一方面,

ToArrayIEnumerable<T>上的扩展方法。由于您的班级同时为IEnumerable<string>IEnumerable<char[]>,因此两个通用参数stringchar[]之间的调用不明确。