IEnumerable 接口和GetEnumerator 詳解


IEnumerable<T> 接口

.NET Framework 4.6 and 4.5
 

 

公開枚舉數,該枚舉數支持在指定類型的集合上進行簡單迭代。

若要瀏覽此類型的.NET Framework 源代碼,請參閱參考源

 

命名空間:   System.Collections.Generic
程序集:  mscorlib(在 mscorlib.dll 中)
 
 
 
public interface IEnumerable<out T> : IEnumerable

 

類型參數

   out T

要枚舉的對象的類型。

此類型參數是協變。即可以使用指定的類型或派生程度更高的類型。有關協變和逆變的詳細信息,請參閱 泛型中的協變和逆變

IEnumerable<T> 類型公開以下成員。

方法

顯示: 
  名稱 描述
公共方法由 XNA Framework 提供支持受 可移植類庫 支持 GetEnumerator 返回一個循環訪問集合的枚舉器。

 

GetEnumerator 詳解

返回一個循環訪問集合的枚舉器。

命名空間:   System.Collections.Generic
程序集:  mscorlib(mscorlib.dll 中)
 

語法  

IEnumerator<T> GetEnumerator()

 

返回值

Type:  System.Collections.Generic.IEnumerator<T>

用於循環訪問集合的枚舉數。

備注
 
 

返回IEnumerator<T>提供了通過公開來循環訪問集合的能力Current屬性。讀取集合中的數據,但不是能修改集合,您可以使用枚舉器。

最初,枚舉數位於集合中的第一個元素之前。在此位置上,Current是不確定的。因此,您必須調用MoveNext方法使枚舉器前進到之前讀取值的集合的第一個元素Current

Current返回同一個對象,直到MoveNext作為再次調用MoveNext設置Current到下一個元素。

如果MoveNext越過集合,該枚舉數的末尾將被定位在集合中的最后一個元素之后和MoveNext返回false當枚舉數位於此位置上,對后續調用MoveNext也會返回false如果最后一次調用到MoveNext返回falseCurrent是不確定的。您不能設置Current再次為集合的第一個元素必須改為創建新的枚舉器實例。

一個枚舉器沒有對集合的獨占訪問,因此,只要集合保持不變,枚舉器保持有效。如果進行了更改到集合中,如添加、 修改,或刪除元素),則枚舉器將失效,並可能會收到意外的結果時。此外,對集合進行枚舉不是線程安全過程。若要保證線程安全,您應枚舉期間鎖定集合,或實現同步對集合。

集合中的默認實現System.Collections.Generic命名空間時不同步。

 

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class App
{
    // Excercise the Iterator and show that it's more
    // performant.
    public static void Main()
    {
        TestStreamReaderEnumerable();
        Console.WriteLine("---");
        TestReadingFile();
    }

    public static void TestStreamReaderEnumerable()
    {
        // Check the memory before the iterator is used.
        long memoryBefore = GC.GetTotalMemory(true);
      IEnumerable<String> stringsFound;
        // Open a file with the StreamReaderEnumerable and check for a string.
      try {
         stringsFound =
               from line in new StreamReaderEnumerable(@"c:\temp\tempFile.txt")
               where line.Contains("string to search for")
               select line;
         Console.WriteLine("Found: " + stringsFound.Count());
      }
      catch (FileNotFoundException) {
         Console.WriteLine(@"This example requires a file named C:\temp\tempFile.txt.");
         return;
      }

        // Check the memory after the iterator and output it to the console.
        long memoryAfter = GC.GetTotalMemory(false);
        Console.WriteLine("Memory Used With Iterator = \t"
            + string.Format(((memoryAfter - memoryBefore) / 1000).ToString(), "n") + "kb");
    }

    public static void TestReadingFile()
    {
        long memoryBefore = GC.GetTotalMemory(true);
      StreamReader sr;
      try {
         sr = File.OpenText("c:\\temp\\tempFile.txt");
      }
      catch (FileNotFoundException) {
         Console.WriteLine(@"This example requires a file named C:\temp\tempFile.txt.");
         return;
      }

        // Add the file contents to a generic list of strings.
        List<string> fileContents = new List<string>();
        while (!sr.EndOfStream) {
            fileContents.Add(sr.ReadLine());
        }

        // Check for the string.
        var stringsFound = 
            from line in fileContents
            where line.Contains("string to search for")
            select line;

        sr.Close();
        Console.WriteLine("Found: " + stringsFound.Count());

        // Check the memory after when the iterator is not used, and output it to the console.
        long memoryAfter = GC.GetTotalMemory(false);
        Console.WriteLine("Memory Used Without Iterator = \t" + 
            string.Format(((memoryAfter - memoryBefore) / 1000).ToString(), "n") + "kb");
    }
}

// A custom class that implements IEnumerable(T). When you implement IEnumerable(T), 
// you must also implement IEnumerable and IEnumerator(T).
public class StreamReaderEnumerable : IEnumerable<string>
{
    private string _filePath;
    public StreamReaderEnumerable(string filePath)
    {
        _filePath = filePath;
    }

    // Must implement GetEnumerator, which returns a new StreamReaderEnumerator.
    public IEnumerator<string> GetEnumerator()
    {
        return new StreamReaderEnumerator(_filePath);
    }

    // Must also implement IEnumerable.GetEnumerator, but implement as a private method.
    private IEnumerator GetEnumerator1()
    {
        return this.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator1();
    }
}

// When you implement IEnumerable(T), you must also implement IEnumerator(T), 
// which will walk through the contents of the file one line at a time.
// Implementing IEnumerator(T) requires that you implement IEnumerator and IDisposable.
public class StreamReaderEnumerator : IEnumerator<string>
{
    private StreamReader _sr;
    public StreamReaderEnumerator(string filePath)
    {
        _sr = new StreamReader(filePath);
    }

    private string _current;
    // Implement the IEnumerator(T).Current publicly, but implement 
    // IEnumerator.Current, which is also required, privately.
    public string Current
    {

        get
        {
            if (_sr == null || _current == null)
            {
                throw new InvalidOperationException();
            }

            return _current;
        }
    }

    private object Current1
    {

        get { return this.Current; }
    }

    object IEnumerator.Current
    {
        get { return Current1; }
    }

    // Implement MoveNext and Reset, which are required by IEnumerator.
    public bool MoveNext()
    {
        _current = _sr.ReadLine();
        if (_current == null)
            return false;
        return true;
    }

    public void Reset()
    {
        _sr.DiscardBufferedData();
        _sr.BaseStream.Seek(0, SeekOrigin.Begin);
        _current = null;
    }

    // Implement IDisposable, which is also implemented by IEnumerator(T).
    private bool disposedValue = false;
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposedValue)
        {
            if (disposing)
            {
                // Dispose of managed resources.
            }
            _current = null;
            if (_sr != null) {
               _sr.Close();
               _sr.Dispose();
            }
        }

        this.disposedValue = true;
    }

     ~StreamReaderEnumerator()
    {
        Dispose(false);
    }
}
// This example displays output similar to the following:
//       Found: 2
//       Memory Used With Iterator =     33kb
//       ---
//       Found: 2
//       Memory Used Without Iterator =  206kb

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM