yield return

一、结论

使用yield return得到的集合相较于直接使用list,在于yield return支持延迟加载,也就是说,对于一个有一百万数据量的集合,只使用了前五项。如果使用yield return,在内存中只会加载前五项的数据,但是使用list就会将一百万的数据一次性全部加载到内存中。懒加载在大多数情况下都是有利的。

二、实验过程

  1. 建立一个数据类,并跟踪使用yield和list获取数据的过程
  2. public class Dashboard
    {
        public float[] temps = new float[10]
        {
             56.2F,56.7F,56.9F,58.8F,61.3F,65.9F,62.1F,59.2F,57.5F,56.5F
        };
        public List<float> GetFloatList()
        {
            List<float> list = new List<float>();
            foreach (var item in temps)
            {
                if (item > 57)
                {
                    Console.WriteLine("执行一次list");
                    list.Add(item);
                }
            }
            return list;
        }
    
        public IEnumerable<float> GetFloatEnum()
        {
            foreach (var item in temps)
            {
                if (item > 57)
                {
                    Console.WriteLine("执行一次yield return");
                    yield return item;
                }
            }
        }
    }
    
  3. 使用yield return和list,比较执行结果执
  4. Dashboard dashboard = new Dashboard();
    var result2 = dashboard.GetFloatEnum();
    Console.WriteLine(result2.First());
    
    Console.WriteLine("please press enter...");
    Console.ReadKey();
    
    var result3 = dashboard.GetFloatList();
    Console.WriteLine(result3.First());
    
    Console.ReadLine();
    
    /*
        * //延迟加载
        执行一次yield return
        58.8
        please press enter...
        执行一次list
        执行一次list
        执行一次list
        执行一次list
        执行一次list
        执行一次list
        58.8
        */
    由此可见,再只取用集合的第一项的时候,yield return只执行了一次,而list却执行了很多次。
  5. 在IEnumerable上调用ToList(),并比较执行结果
  6. Dashboard dashboard = new Dashboard();
    var result2 = dashboard.GetFloatEnum();
    Console.WriteLine(result2.ToList()[0]);
    
    Console.WriteLine("please press enter...");
    Console.ReadKey();
    
    var result3 = dashboard.GetFloatList();
    Console.WriteLine(result3[0]);
    
    Console.ReadLine();
    
    //一旦调用tolist就失去延迟加载的效果,在调用tolist的过程中将所有集合执行完
    执行一次yield return
    执行一次yield return
    执行一次yield return
    执行一次yield return
    执行一次yield return
    执行一次yield return
    58.8
    please press enter...
    执行一次list
    执行一次list
    执行一次list
    执行一次list
    执行一次list
    执行一次list
    58.8  

    结论:在IEnumerable上调用ToList()会致使代码执行所有迭代,效果等同于直接使用List。

    三、使用技巧实例

    下面示例一个较复杂的自定义集合的使用,一般使用形式如下:

    private IEnumerable<TankReading> ConvertToTankReadings(DataTable dataTable)
    {
        var tankReadings = new List<TankReading>();
        foreach (DataRow row in dataTable.Rows)
        {
            var tankReading = new TankReading
            {
                TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
                TankID = Convert.ToInt32(row["TankID"]),
                ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
                ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
                ReadingInches = Convert.ToInt32(row["ReadingInches"]),
                MaterialNumber = row["MaterialNumber"].ToString(),
                EnteredBy = row["EnteredBy"].ToString(),
                ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
                MaterialID = Convert.ToInt32(row["MaterialID"]),
                Submitted = Convert.ToBoolean(row["Submitted"]),
            };
            tankReadings.Add(tankReading);
        }
        return tankReadings.AsEnumerable();
    }
    
    

    采用yield实现懒加载如下,建议采用懒加载的方法

    private IEnumerable<TankReading> ConvertToTankReadings(DataTable dataTable)
    {
        foreach (DataRow row in dataTable.Rows)
        {
            yield return new TankReading
            {
                TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
                TankID = Convert.ToInt32(row["TankID"]),
                ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
                ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
                ReadingInches = Convert.ToInt32(row["ReadingInches"]),
                MaterialNumber = row["MaterialNumber"].ToString(),
                EnteredBy = row["EnteredBy"].ToString(),
                ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
                MaterialID = Convert.ToInt32(row["MaterialID"]),
                Submitted = Convert.ToBoolean(row["Submitted"]),
            };
        }
    
    }

    猜你喜欢

    转载自blog.csdn.net/u010178308/article/details/81016933