601 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			601 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C#
		
	
	
| 
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
| using System.Linq.Expressions;
 | |
| using System.Threading;
 | |
| using System.Threading.Tasks;
 | |
| 
 | |
| namespace IRaCIS.Core.Infrastructure.Extention
 | |
| {
 | |
|     public static partial class IEnumerableExtensions
 | |
|     {
 | |
| 
 | |
|         ///// <summary>
 | |
|         ///// 按字段去重
 | |
|         ///// </summary>
 | |
|         ///// <typeparam name="TSource"></typeparam>
 | |
|         ///// <typeparam name="TKey"></typeparam>
 | |
|         ///// <param name="source"></param>
 | |
|         ///// <param name="keySelector"></param>
 | |
|         ///// <returns></returns>
 | |
|         //public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
 | |
|         //{
 | |
|         //    var hash = new HashSet<TKey>();
 | |
|         //    return source.Where(p => hash.Add(keySelector(p)));
 | |
|         //}
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 添加多个元素
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="this"></param>
 | |
|         /// <param name="values"></param>
 | |
|         public static void AddRange<T>(this ICollection<T> @this, params T[] values)
 | |
|         {
 | |
|             foreach (var obj in values)
 | |
|             {
 | |
|                 @this.Add(obj);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 添加符合条件的多个元素
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="this"></param>
 | |
|         /// <param name="predicate"></param>
 | |
|         /// <param name="values"></param>
 | |
|         public static void AddRangeIf<T>(this ICollection<T> @this, Func<T, bool> predicate, params T[] values)
 | |
|         {
 | |
|             foreach (var obj in values)
 | |
|             {
 | |
|                 if (predicate(obj))
 | |
|                 {
 | |
|                     @this.Add(obj);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 添加不重复的元素
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="this"></param>
 | |
|         /// <param name="values"></param>
 | |
|         public static void AddRangeIfNotContains<T>(this ICollection<T> @this, params T[] values)
 | |
|         {
 | |
|             foreach (T obj in values)
 | |
|             {
 | |
|                 if (!@this.Contains(obj))
 | |
|                 {
 | |
|                     @this.Add(obj);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 移除符合条件的元素
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="this"></param>
 | |
|         /// <param name="where"></param>
 | |
|         public static void RemoveWhere<T>(this ICollection<T> @this, Func<T, bool> @where)
 | |
|         {
 | |
|             foreach (var obj in @this.Where(where).ToList())
 | |
|             {
 | |
|                 @this.Remove(obj);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 在元素之后添加元素
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="list"></param>
 | |
|         /// <param name="condition">条件</param>
 | |
|         /// <param name="value">值</param>
 | |
|         public static void InsertAfter<T>(this IList<T> list, Func<T, bool> condition, T value)
 | |
|         {
 | |
|             foreach (var item in list.Select((item, index) => new { item, index }).Where(p => condition(p.item)).OrderByDescending(p => p.index))
 | |
|             {
 | |
|                 if (item.index + 1 == list.Count)
 | |
|                 {
 | |
|                     list.Add(value);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     list.Insert(item.index + 1, value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 在元素之后添加元素
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="list"></param>
 | |
|         /// <param name="index">索引位置</param>
 | |
|         /// <param name="value">值</param>
 | |
|         public static void InsertAfter<T>(this IList<T> list, int index, T value)
 | |
|         {
 | |
|             foreach (var item in list.Select((v, i) => new { Value = v, Index = i }).Where(p => p.Index == index).OrderByDescending(p => p.Index))
 | |
|             {
 | |
|                 if (item.Index + 1 == list.Count)
 | |
|                 {
 | |
|                     list.Add(value);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     list.Insert(item.Index + 1, value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 转HashSet
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <returns></returns>
 | |
|         public static HashSet<TResult> ToHashSet<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector)
 | |
|         {
 | |
|             var set = new HashSet<TResult>();
 | |
|             set.UnionWith(source.Select(selector));
 | |
|             return set;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 遍历IEnumerable
 | |
|         /// </summary>
 | |
|         /// <param name="objs"></param>
 | |
|         /// <param name="action">回调方法</param>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         public static void ForEach<T>(this IEnumerable<T> objs, Action<T> action)
 | |
|         {
 | |
|             foreach (var o in objs)
 | |
|             {
 | |
|                 action(o);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 异步foreach
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="maxParallelCount">最大并行数</param>
 | |
|         /// <param name="action"></param>
 | |
|         /// <param name="cancellationToken"></param>
 | |
|         /// <returns></returns>
 | |
|         public static async Task ForeachAsync<T>(this IEnumerable<T> source, Func<T, Task> action, int maxParallelCount, CancellationToken cancellationToken = default)
 | |
|         {
 | |
|             var list = new List<Task>();
 | |
|             foreach (var item in source)
 | |
|             {
 | |
|                 if (cancellationToken.IsCancellationRequested)
 | |
|                 {
 | |
|                     return;
 | |
|                 }
 | |
| 
 | |
|                 list.Add(action(item));
 | |
|                 if (list.Count >= maxParallelCount)
 | |
|                 {
 | |
|                     await Task.WhenAll(list);
 | |
|                     list.Clear();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             await Task.WhenAll(list);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 异步foreach
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="action"></param>
 | |
|         /// <returns></returns>
 | |
|         public static Task ForeachAsync<T>(this IEnumerable<T> source, Func<T, Task> action, CancellationToken cancellationToken = default)
 | |
|         {
 | |
|             return ForeachAsync(source, action, source.Count(), cancellationToken);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 异步Select
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <returns></returns>
 | |
|         public static Task<TResult[]> SelectAsync<T, TResult>(this IEnumerable<T> source, Func<T, Task<TResult>> selector)
 | |
|         {
 | |
|             return Task.WhenAll(source.Select(selector));
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 异步Select
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <returns></returns>
 | |
|         public static Task<TResult[]> SelectAsync<T, TResult>(this IEnumerable<T> source, Func<T, int, Task<TResult>> selector)
 | |
|         {
 | |
|             return Task.WhenAll(source.Select(selector));
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 异步For
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <param name="maxParallelCount">最大并行数</param>
 | |
|         /// <param name="cancellationToken">取消口令</param>
 | |
|         /// <returns></returns>
 | |
|         public static async Task ForAsync<T>(this IEnumerable<T> source, Func<T, int, Task> selector, int maxParallelCount, CancellationToken cancellationToken = default)
 | |
|         {
 | |
|             var list = new List<Task>();
 | |
|             int index = 0;
 | |
|             foreach (var item in source)
 | |
|             {
 | |
|                 if (cancellationToken.IsCancellationRequested)
 | |
|                 {
 | |
|                     return;
 | |
|                 }
 | |
| 
 | |
|                 list.Add(selector(item, index++));
 | |
|                 if (list.Count >= maxParallelCount)
 | |
|                 {
 | |
|                     await Task.WhenAll(list);
 | |
|                     list.Clear();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             await Task.WhenAll(list);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 异步For
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <param name="cancellationToken">取消口令</param>
 | |
|         /// <returns></returns>
 | |
|         public static Task ForAsync<T>(this IEnumerable<T> source, Func<T, int, Task> selector, CancellationToken cancellationToken = default)
 | |
|         {
 | |
|             return ForAsync(source, selector, source.Count(), cancellationToken);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最大值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TResult MaxOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
 | |
|             => source.Select(selector).DefaultIfEmpty().Max();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最大值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <param name="defaultValue"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TResult MaxOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Max();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最大值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TSource MaxOrDefault<TSource>(this IQueryable<TSource> source) => source.DefaultIfEmpty().Max();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最大值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="defaultValue"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TSource MaxOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Max();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最大值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <param name="defaultValue"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TResult MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Max();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最大值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TResult MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) => source.Select(selector).DefaultIfEmpty().Max();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最大值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TSource MaxOrDefault<TSource>(this IEnumerable<TSource> source) => source.DefaultIfEmpty().Max();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最大值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="defaultValue"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TSource MaxOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Max();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最小值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector) => source.Select(selector).DefaultIfEmpty().Min();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最小值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <param name="defaultValue"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Min();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最小值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source) => source.DefaultIfEmpty().Min();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最小值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="defaultValue"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Min();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最小值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) => source.Select(selector).DefaultIfEmpty().Min();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最小值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <typeparam name="TResult"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="selector"></param>
 | |
|         /// <param name="defaultValue"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Min();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最小值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source) => source.DefaultIfEmpty().Min();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 取最小值
 | |
|         /// </summary>
 | |
|         /// <typeparam name="TSource"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <param name="defaultValue"></param>
 | |
|         /// <returns></returns>
 | |
|         public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Min();
 | |
| 
 | |
|         ///// <summary>
 | |
|         ///// 标准差
 | |
|         ///// </summary>
 | |
|         ///// <typeparam name="T"></typeparam>
 | |
|         ///// <param name="source"></param>
 | |
|         ///// <param name="selector"></param>
 | |
|         ///// <returns></returns>
 | |
|         //public static TResult StandardDeviation<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector) where TResult : IConvertible
 | |
|         //{
 | |
|         //    return StandardDeviation(source.Select(t => selector(t).ConvertTo<double>())).ConvertTo<TResult>();
 | |
|         //}
 | |
| 
 | |
|         ///// <summary>
 | |
|         ///// 标准差
 | |
|         ///// </summary>
 | |
|         ///// <typeparam name="T"></typeparam>
 | |
|         ///// <param name="source"></param>
 | |
|         ///// <returns></returns>
 | |
|         //public static T StandardDeviation<T>(this IEnumerable<T> source) where T : IConvertible
 | |
|         //{
 | |
|         //    return StandardDeviation(source.Select(t => t.ConvertTo<double>())).ConvertTo<T>();
 | |
|         //}
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 标准差
 | |
|         /// </summary>
 | |
|         /// <param name="source"></param>
 | |
|         /// <returns></returns>
 | |
|         public static double StandardDeviation(this IEnumerable<double> source)
 | |
|         {
 | |
|             double result = 0;
 | |
|             int count = source.Count();
 | |
|             if (count > 1)
 | |
|             {
 | |
|                 double avg = source.Average();
 | |
|                 double sum = source.Sum(d => (d - avg) * (d - avg));
 | |
|                 result = Math.Sqrt(sum / count);
 | |
|             }
 | |
| 
 | |
|             return result;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 随机排序
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="source"></param>
 | |
|         /// <returns></returns>
 | |
|         public static IOrderedEnumerable<T> OrderByRandom<T>(this IEnumerable<T> source)
 | |
|         {
 | |
|             return source.OrderBy(_ => Guid.NewGuid());
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 序列相等
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="first"></param>
 | |
|         /// <param name="second"></param>
 | |
|         /// <param name="condition"></param>
 | |
|         /// <returns></returns>
 | |
|         public static bool SequenceEqual<T>(this IEnumerable<T> first, IEnumerable<T> second, Func<T, T, bool> condition)
 | |
|         {
 | |
|             if (first is ICollection<T> source1 && second is ICollection<T> source2)
 | |
|             {
 | |
|                 if (source1.Count != source2.Count)
 | |
|                 {
 | |
|                     return false;
 | |
|                 }
 | |
| 
 | |
|                 if (source1 is IList<T> list1 && source2 is IList<T> list2)
 | |
|                 {
 | |
|                     int count = source1.Count;
 | |
|                     for (int index = 0; index < count; ++index)
 | |
|                     {
 | |
|                         if (!condition(list1[index], list2[index]))
 | |
|                         {
 | |
|                             return false;
 | |
|                         }
 | |
|                     }
 | |
|                     return true;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             using IEnumerator<T> enumerator1 = first.GetEnumerator();
 | |
|             using IEnumerator<T> enumerator2 = second.GetEnumerator();
 | |
|             while (enumerator1.MoveNext())
 | |
|             {
 | |
|                 if (!enumerator2.MoveNext() || !condition(enumerator1.Current, enumerator2.Current))
 | |
|                 {
 | |
|                     return false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return !enumerator2.MoveNext();
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 序列相等
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T1"></typeparam>
 | |
|         /// <typeparam name="T2"></typeparam>
 | |
|         /// <param name="first"></param>
 | |
|         /// <param name="second"></param>
 | |
|         /// <param name="condition"></param>
 | |
|         /// <returns></returns>
 | |
|         public static bool SequenceEqual<T1, T2>(this IEnumerable<T1> first, IEnumerable<T2> second, Func<T1, T2, bool> condition)
 | |
|         {
 | |
|             if (first is ICollection<T1> source1 && second is ICollection<T2> source2)
 | |
|             {
 | |
|                 if (source1.Count != source2.Count)
 | |
|                 {
 | |
|                     return false;
 | |
|                 }
 | |
| 
 | |
|                 if (source1 is IList<T1> list1 && source2 is IList<T2> list2)
 | |
|                 {
 | |
|                     int count = source1.Count;
 | |
|                     for (int index = 0; index < count; ++index)
 | |
|                     {
 | |
|                         if (!condition(list1[index], list2[index]))
 | |
|                         {
 | |
|                             return false;
 | |
|                         }
 | |
|                     }
 | |
|                     return true;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             using IEnumerator<T1> enumerator1 = first.GetEnumerator();
 | |
|             using IEnumerator<T2> enumerator2 = second.GetEnumerator();
 | |
|             while (enumerator1.MoveNext())
 | |
|             {
 | |
|                 if (!enumerator2.MoveNext() || !condition(enumerator1.Current, enumerator2.Current))
 | |
|                 {
 | |
|                     return false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return !enumerator2.MoveNext();
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 对比两个集合哪些是新增的、删除的、修改的
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T1"></typeparam>
 | |
|         /// <typeparam name="T2"></typeparam>
 | |
|         /// <param name="olds"></param>
 | |
|         /// <param name="news"></param>
 | |
|         /// <param name="key1Selector">对比因素属性</param>
 | |
|         /// <param name="key2Selector">对比因素属性</param>
 | |
|         /// <returns></returns>
 | |
|         public static (List<T2> adds, List<T1> remove, List<T1> updates) CompareChanges<T1, T2>(this IEnumerable<T1> olds, IEnumerable<T2> news, Func<T1, object> key1Selector, Func<T2, object> key2Selector)
 | |
|         {
 | |
|             return (news.Where(c => olds.All(m => key1Selector(m) != key2Selector(c))).ToList(), olds.Where(m => news.All(c => key2Selector(c) != key1Selector(m))).ToList(), olds.Where(m => news.Any(c => key1Selector(m) == key2Selector(c))).ToList());
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 对比两个集合哪些是新增的、删除的、修改的
 | |
|         /// </summary>
 | |
|         /// <typeparam name="T"></typeparam>
 | |
|         /// <param name="olds"></param>
 | |
|         /// <param name="news"></param>
 | |
|         /// <param name="keySelector">对比因素属性</param>
 | |
|         /// <returns></returns>
 | |
|         public static (List<T> adds, List<T> remove, List<T> updates) CompareChanges<T>(this IEnumerable<T> olds, IEnumerable<T> news, Func<T, object> keySelector)
 | |
|         {
 | |
|             return (news.Where(c => olds.All(m => keySelector(m) != keySelector(c))).ToList(), olds.Where(m => news.All(c => keySelector(c) != keySelector(m))).ToList(), olds.Where(m => news.Any(c => keySelector(m) == keySelector(c))).ToList());
 | |
|         }
 | |
|     }
 | |
| }
 |