2009-06-02 74 views
6

我很好奇,想看看SingleOrFallback方法是如何在MoreLinq實現,發現這是我從來沒有見過的:C#:IEnumerator的<T>在using語句

public static T SingleOrFallback<T>(this IEnumerable<T> source, Func<T> fallback) 
    { 
     source.ThrowIfNull("source"); 
     fallback.ThrowIfNull("fallback"); 
     using (IEnumerator<T> iterator = source.GetEnumerator()) 
     { 
      if (!iterator.MoveNext()) 
      { 
       return fallback(); 
      } 
      T first = iterator.Current; 
      if (iterator.MoveNext()) 
      { 
       throw new InvalidOperationException(); 
      } 
      return first; 
     } 
    } 

爲什麼在using聲明IEnumerator<T>?當在IEnumerable<T>上使用foreach時,這是應該考慮的事情嗎?

旁邊的問題:這種方法到底做了什麼?當源序列不包含一個項目時是否返回後備項目?

回答

11

IEnumerator<T>延伸IDisposable,所以你應該它在一個using語句。 foreach自動執行此操作。 (非通用IEnumerator擴展IDisposable但C#編譯器仍然生成代碼以有條件地調用Dispose。這是C#1.0和1.2之間的(少數)更改之一,其中1.2是使用.NET 1.1發佈的版本,出於某種原因)。

Here's an article解釋了爲什麼這在迭代器塊的上下文中很重要。

至於方法做什麼:

  • 如果序列是空的,返回的後備項目
  • 如果序列都只有一個項目,其返回
  • 如果序列有不止一個項目,拋出一個異常

PS:很高興見到MoreLinq越來越一些注意:)

+1

呵呵,是的。由於MaxBy和MinBy方法,將它添加到我們的項目中。當添加這樣的東西時,你總是要檢查是否還有其他東西可以使用;) – Svish 2009-06-02 10:52:58

0

如果Dispose未被調用,某些枚舉器將表現得很差;對於非泛型的泛型應用(非泛型應用要求代碼要麼鴨式鍵入Dispose調用,要麼轉換爲IDisposable,然後調用IDisposable.Dispose),這也是如此。確保IEnumerator對象被丟棄是一個習慣性的問題;我認爲有必要驗證任何接受IEnumerable類型未知的例程的正確性。