【c#】我们为什么要用 yield return

声明:本文部分内容来自 《more effective c#》,特此声明

c# 里面的 yield return 没什么高大上的,就是一个一个的 return。但是我们不能小看这种用法,他能给编程带来很多性能上的提高以及用法上的方便(减少遍历次数,增加重用性)。

我们来看一个例子:

对于函数

        public static List<int> Unique(IEnumerable<int> nums)
        {
            List<int> uniqueVals = new List<int>();

            foreach(int num in nums)
            {
                if(!uniqueVals.ContainsKey(num))
                {
                    uniqueVals.Add(num);
                    Console.WriteLine(num);
                }
            }
            return uniqueVals;
        }

不难理解,传进来一个数组,比如说是一个 list,返回一个去重的 list 出去,简单明了,事实上,这个函数如果不需要复用的话,没有任何问题。但是,作为程序员,我们遇到不需要复用的情形实际上是非常少的。

比方说,现在有一个要求,让你把一个去重的 list 乘方,你会怎么做,我们可能很自然的想到,把这个 Unique 函数的输出结果当做输入传到另一个乘方函数里面,然后再遍历一遍即可解决。

可是,这样的问题是,我们完全可以把去重和乘方放在一次遍历里面一起解决啊,你这样多遍历了一次,增加了时间复杂度。

又有同学可能要说,我们直接去改 Unque 函数不就行了吗,再里面添加一段乘方逻辑。好,这样的话我再问你,比方说现在又有一个需求,让你把一个 list 去重以后开方,你怎么办?你是要再写一个新的函数么?这样的话,你这两个函数里面都有 list 去重这段逻辑,造成了代码冗余,这是软件工程的禁忌。

那怎么办?yield return 可以完美的解决这个问题,以上面的去重乘方需求为例,我们可以把 Unique 函数改写为:

        public static IEnumerable<int> Unique2(IEnumerable<int> nums)
        {
            List<int> uniqueVals = new List<int>();

            foreach(int num in nums)
            {
                if (!uniqueVals.ContainsKey(num))
                {
                    uniqueVals.Add(num);
                    yield return num;
                }
            }
        }

接着,我们写乘方函数,同样使用 yield return

        public static IEnumerable<int> Square(IEnumerable<int> nums)
        {
            foreach (var num in nums)
                yield return num * num;
        }

使用时,我们直接进行函数嵌套即可,我们可以通过一个 for 循环查看一下结果:

            var l = new List<int> { 0, 3, 4, 5, 7, 3, 2, 7, 8, 0 ,3, 1};
            foreach (int num in Square(Unique2(l)))
                Console.WriteLine($"{num}");

仅遍历一次,复用性良好,yield return 的好处,你现在了解了吗?

原文地址:https://www.cnblogs.com/chinasoft/p/14961468.html