C#-Linq源码解析之DefaultIfEmpty

前言

在Dotnet开发过程中,DefaultIfEmpty作为IEnumerable的扩展方法,十分常用。本文对DefaultIfEmpty方法的关键源码进行简要分析,以方便大家日后更好的使用该方法。.

使用

DefaultIfEmpty 返回 IEnumerable< T> 的元素;如果序列为空,则返回一个具有默认值的单例类集合。

假如我们有这样的一个集合,如果集合的元素为空,我们给该集合添加一个默认元素.

 public class UserInforMation
    {
        public string UserName { get; set; }
        public string Sex { get; set; }
      
    }
List<UserInforMation> lstUserInforMations = new List<UserInforMation>();
  • 不使用Linq 我们可能会这样写
 private List<UserInforMation> DefaultIfEmpty(List<UserInforMation> userInforMations, UserInforMation defaultUser)
 {
            if (userInforMations == null)
            {
                throw new Exception("数据源为空");
            }

            if (userInforMations.Any())
            {
                return userInforMations;
            }
            else
            {
                userInforMations.Add(defaultUser);
                return userInforMations;
            }
}
  • 使用Linq
lstUserInforMations.DefaultIfEmpty(new UserInforMation { UserName = "张三", Sex = "男" });

源码解析

方法

 public static IEnumerable<TSource> DefaultIfEmpty<TSource>(IEnumerable<TSource> source, TSource defaultValue)
参数
  • source 返回的序列。
  • defaultValue 序列为空时要返回的默认值。
返回值
  • IEnumerable< TSource> 如果 source 为空,则为包含 defaultValue 的 IEnumerable< T>;否则为 source。

此方法通过使用延迟执行来实现,因为IEnumerable是延迟加载的,每次访问的时候才取值。所以我们在返回数据时需要使用yield

由于我们需要判断当前集合是否有元素,所以我们需要使用到GetEnumerator()

源码
   public static IEnumerable<TSource> DefaultIfEmpty<TSource>(IEnumerable<TSource> source, TSource defaultValue)
        {
            if (source == null)
            {
                throw new Exception("source is null");
            }
           using (IEnumerator<TSource> e = source.GetEnumerator())
            {
                if (e.MoveNext())
                {
                    do
                    {
                        yield return e.Current;
                    }
                    while (e.MoveNext());
                }
                else
                {
                    yield return defaultValue;
                }
            }
        }

总结

此方法本人用于处理空集合。该方法显示默认值,而不是显示错误。

List<UserInforMation> lstUserInforMations = new List<UserInforMation>();
var userInfor = lstUserInforMations.FirstOrDefault();
if (userInfor == null)
 {
    userInfor = new UserInforMation { UserName = "张三", Sex = "男" };
  }

使用DefaultIfEmpty可以让代码变得更优雅一点

 List<UserInforMation> lstUserInforMations = new List<UserInforMation>();
 var userInfor = lstUserInforMations
                 .DefaultIfEmpty(new UserInforMation { UserName = "张三", Sex = "男" })
                 .First();