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

    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();
        }
    }
    

现在,这工作得很好,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< char[] > 和 IEnumerable< string > 并且可能无法确定我想调用其中的哪一个,但为什么它在“foreach”示例中运行良好?

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

4

2 回答 2

2

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

检查这个问题:如何在 C# 中实现 foreach?

这就是为什么您的课程使用foreach和不使用ToArray().

于 2013-07-15T11:40:49.397 回答
2

区别如下:

foreach实际上寻找一个名为GetEnumerator. 它真的不在乎IEnumerable<T>。您的类B只有一个名为GetEnumerator的公共方法:定义在B其中的方法隐藏在 中定义的方法A

ToArray另一方面是 . 上的扩展方法IEnumerable<T>。由于您的课程是两者IEnumerable<string>,并且IEnumerable<char[]>两个通用参数之间的调用不明确,string并且char[].

于 2013-07-15T11:44:50.200 回答