因为要取两个集合不同的元素,所以写了个拓展方法,用到了yield这个关键字,然后就学习了一波。先上代码
public static IEnumerable<T> NoRetainAll<T>(this IList<T> source, IList<T> compareSource) { foreach (var info in source) { if (!compareSource.Contains(info)) yield return info; } }
yield return与return的区别
返回值类型:
return 可以返回任意类型T;
yield return 只能返回IEnumerable<T>类型,总是个可枚举的对象,yield return 后面的表达式为T类型。如果没有元素,也会返回一个count=0的IEnumerable<T>结果,所以不会出现NULL
程序控制流程不同:
return 语句使方法返回,后面再有语句都不执行了。
yield return 则不会使方法返回,继续执行后面的语句,只是计算记录最终返回的可枚举对象的一个元素值
这篇文章介绍的两者的区别还挺详细https://www.cnblogs.com/fanyf/p/4565385.html。
上述方法参数为什么要用IList<T>作类型了,因为用IEnumerable<T>,编译器里面的Reshaper警告提示 Possible multiple enumeration of IEnumerable
这篇文章介绍了原因https://blog.csdn.net/aixun4106/article/details/101972058,还给出了例子,
分析:如果对IEnumerable多次读取操作,会有因数据源改变导致前后两次枚举项不固定的风险,最突出例子是读取数据库的时候,第二次foreach时恰好数据源发生了改变,那么读取出来的数据和第一次就不一致了。
解决方案:多次使用IEnumerable时,最好转换为List或者Array
个人理解:IEnumerable相当于懒加载,就是数据不是一次性到内存里面的,而List是一次性到内存当中的,所以IEnumerable可能会改变,而List不会改变