Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 警告-不执行';收集';图案_C#_Foreach_Ienumerable_Compiler Warnings - Fatal编程技术网

C# 警告-不执行';收集';图案

C# 警告-不执行';收集';图案,c#,foreach,ienumerable,compiler-warnings,C#,Foreach,Ienumerable,Compiler Warnings,我正在创建集合,显式实现IEnumerable,并尝试从内部迭代它: public class MyCollection<T> : IEnumerable<T>, IEnumerable { IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnum

我正在创建集合,显式实现
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
    }
}

我做错什么了吗?

请参阅此处的编译器警告CS0279说明:

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


(emphasis mine)

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

在您的例子中,它可以找到单个无参数的
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); }
    

就这么叫它别的吧<代码>GetEnumeratorImpl?或者不要对
IEnumerable.GetEnumerator?
@JonSkeet使用显式接口实现,所以它是唯一的名称限定编译器?是的-因为
foreach
中的模式匹配找到
GetEnumerator()
方法,但无法使用它。现在添加答案…不是重点。了解接口实现。外部
foreach
不需要任何显式方法公开。事实上,您不能将显式实现公开。我认为第二个选项是最干净的。我明显的错误是显式地实现了这两个接口,只需要实现一个。谢谢
IEnumerator IEnumerable.GetEnumerator() => GetEnumeratorImpl();
IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumeratorImpl();
IEnumerator<T> GetEnumeratorImpl() { yield return default(T); }
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator<T> GetEnumerator() => { yield return default(T); }
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<T>) this).GetEnumerator();
IEnumerator<T> IEnumerable<T>.GetEnumerator() => { yield return default(T); }