2017-08-15 111 views
-1

我正在收集,實施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 

難道我做錯了什麼?

+0

叫它別的東西嗎? 'GetEnumeratorImpl'?或者只是不使用顯式接口實現'IEnumerable .GetEnumerator?' –

+0

@JonSkeet,所以它只是名稱編譯器? – Sinatr

+0

是的 - 因爲'foreach' *中的模式匹配找到* GetEnumerator()'方法,但不能使用它。現在添加一個答案... –

回答

4

警告的存在是因爲C#編譯器可以在許多不同的方式來處理foreach。其中一種方法是找到具有合適返回類型的GetEnumerator方法。在之前檢查編譯器檢查表達式的類型是否實現IEnumerableIEnumerable<T>

在你的情況下,它可以找到單參數GetEnumerator方法,但它不是公開的。 C#規範建議在此處發出警告,因爲您可能有意圖它可用於foreach。從C#5屬,節8.8.4,重點煤礦:使用所得到的方法組和一個空的參數列表

  • 執行重載解析。如果重載解析導致沒有適用的方法,導致模糊不清,或者導致單個最佳方法,但是該方法是靜態或未公開,請檢查可枚舉接口,如下所述。 如果重載解析產生除明確的公共實例方法或沒有適用方法之外的任何內容,則建議發出警告。

以下任何可以解決這個問題的:

  • 重命名GetEnumeratorGetEnumeratorImpl或類似:

    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.GetEnumeratorthisIEnumerable<T>叫它:

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

第二種選擇是我認爲的最清潔。我明顯的錯誤是明確地實現兩個接口,只有一個必須是。謝謝。 – Sinatr

2

見這裏編譯器警告CS0279的解釋:https://msdn.microsoft.com/en-us/library/bz2286x8(v=vs.90).aspx

有在C#中的幾個語句依賴於所限定的圖案,例如 爲的foreach和使用。例如,foreach依靠收集 類實現可枚舉模式。由於 被聲明爲靜態或非公開方法, 編譯器無法進行匹配時發生此錯誤。 模式中的方法需要是實例 的類,並且要公開

(重點煤礦)

+0

不是重點。閱讀[explicit](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation)接口實現。外部'foreach'不需要任何明確的方法來公開。事實上,你**不能**明確實施公開 – Sinatr