警告 - 未实现“集合”模式

时间:2017-08-15 12:34:12

标签: c# foreach ienumerable compiler-warnings

我正在进行收集,明确地实现IEnumerable并尝试从内部迭代它:

public class MyCollection<T> : IEnumerable<T>, IEnumerable
{
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
    IEnumerator<T> GetEnumerator() { yield return default(T); } // test

    public void Test()
    {
        foreach (var item in this) { } // here is warning
    }
}

我在this收到编译器警告:

  

警告CS0279'MyCollection'未实现'集合'模式。 'MyCollection.GetEnumerator()'是静态的还是不公开的。

天哪,它不公开。为什么会这样?我可以将其公开,但foreach类型之外不需要它:

foreach (var item in new MyCollection<string>()) { } // no warning

我做错了吗?

2 个答案:

答案 0 :(得分:4)

警告存在是因为C#编译器可以通过多种不同方式处理foreach。其中一种方法是找到具有合适返回类型的GetEnumerator方法。在之前检查,编译器检查表达式的类型是否实现IEnumerableIEnumerable<T>

在您的情况下,它可以找到单个无参数GetEnumerator方法,但它不公开。此时C#规范建议发出警告,因为您可能打算它可用于foreach。从C#5规范,第8.8.4节,强调我的:

  
      
  • 使用生成的方法组和空参数列表执行重载解析。如果重载决策导致没有适用的方法,导致歧义,或导致单个最佳方法但该方法是静态的或不公开的,请检查可枚举的接口,如下所述。 如果重载决策产生除明确的公共实例方法或没有适用的方法之外的任何内容,建议发出警告。
  •   

以下任何一种方法都可以解决问题:

  • GetEnumerator重命名为GetEnumeratorImpl或类似名称:

    IEnumerator IEnumerable.GetEnumerator() => GetEnumeratorImpl();
    IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumeratorImpl();
    IEnumerator<T> GetEnumeratorImpl() { yield return default(T); }
    
  • 不要对IEnumerable<T>.GetEnumerator()使用显式接口实现 - 将实现放在那里

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    public IEnumerator<T> GetEnumerator() => { yield return default(T); }
    
  • 将实施放在IEnumerable<T>.GetEnumerator中,但将this投放到IEnumerable<T>中的IEnumerable.GetEnumerator进行调用:

    IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<T>) this).GetEnumerator();
    IEnumerator<T> IEnumerable<T>.GetEnumerator() => { yield return default(T); }
    

答案 1 :(得分:2)

请在此处查看编译器警告CS0279的说明:https://msdn.microsoft.com/en-us/library/bz2286x8(v=vs.90).aspx

  

C#中有几个依赖于定义模式的语句,例如   作为foreach 并使用。例如, foreach依赖于集合   实现可枚举模式的类。当发生此错误   由于声明了方法,编译器无法进行匹配   静态或不公开。 模式中的方法必须是实例   课程,并公开

(强调我的)