警告 - 未实现“集合”模式
我正在收集,实施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'没有实现'collection'模式。 'MyCollection.GetEnumerator()'是静态的或不公开的。
地狱是的,它不公开。为什么它应该是?我可以将其公开,但它不需要foreach
类型之外:
foreach (var item in new MyCollection<string>()) { } // no warning
难道我做错了什么?
警告的存在是因为C#编译器可以在许多不同的方式来处理foreach
。其中一种方法是找到具有合适返回类型的GetEnumerator
方法。在之前检查编译器检查表达式的类型是否实现IEnumerable
或IEnumerable<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
,但在IEnumerable.GetEnumerator
投this
到IEnumerable<T>
叫它:IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<T>) this).GetEnumerator(); IEnumerator<T> IEnumerable<T>.GetEnumerator() => { yield return default(T); }
第二种选择是我认为的最清洁。我明显的错误是明确地实现两个接口,只有一个必须是。谢谢。 – Sinatr
见这里编译器警告CS0279的解释:https://msdn.microsoft.com/en-us/library/bz2286x8(v=vs.90).aspx
有在C#中的几个语句依赖于所限定的图案,例如 为的foreach和使用。例如,foreach依靠收集 类实现可枚举模式。由于 被声明为静态或非公开方法, 编译器无法进行匹配时发生此错误。 模式中的方法需要是实例 的类,并且要公开。
(重点煤矿)
不是重点。阅读[explicit](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation)接口实现。外部'foreach'不需要任何明确的方法来公开。事实上,你**不能**明确实施公开 – Sinatr
叫它别的东西吗? 'GetEnumeratorImpl'?或者只是不使用显式接口实现'IEnumerable .GetEnumerator?' –
@JonSkeet,所以它只是名称编译器? – Sinatr
是的 - 因为'foreach' *中的模式匹配找到* GetEnumerator()'方法,但不能使用它。现在添加一个答案... –