• IEnumerable<T> 接口和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:	emp	empFile.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:	emp	empFile.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 = 	"
                + 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:	emp	empFile.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 = 	" + 
                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
     
  • 相关阅读:
    T2038 香甜的黄油 codevs
    缓冲区溢出分析第08课:MS06-040漏洞研究——动态调试
    缓冲区溢出分析第07课:MS06-040漏洞研究——静态分析
    Android最新敲诈者病毒分析及解锁(11月版)
    Android敲诈者病毒“安卓性能激活”分析(2015年9月版)
    Android最新敲诈者病毒分析及解锁
    APK程序Dex文件无源码调试方法讨论
    一个DDOS木马后门病毒的分析
    IDA动态调试Android的DEX文件
    一枚Android "短信小偷" 病毒的分析
  • 原文地址:https://www.cnblogs.com/CandiceW/p/4937299.html
Copyright © 2020-2023  润新知