C#DefaultIfEmpty

示例

如果Sequence不包含任何元素,则使用DefaultIfEmpty返回默认元素。该元素可以是类型的默认值,也可以是该类型的用户定义实例。例:

var chars = new List<string>() { "a", "b", "c", "d" };

chars.DefaultIfEmpty("N/A").FirstOrDefault(); // returns "a";

chars.Where(str =>str.Length> 1)
     .DefaultIfEmpty("N/A").FirstOrDefault(); // return "N/A"

chars.Where(str =>str.Length> 1)
        .DefaultIfEmpty().First(); // 返回null;

左联接中的用法

使用DefaultIfEmpty传统的Linq Join如果找不到匹配项,则可以返回默认对象。因此充当SQL的Left Join。例:

var leftSequence = new List<int>() { 99, 100, 5, 20, 102, 105 };
var rightSequence = new List<char>() { 'a', 'b', 'c', 'i', 'd' };

var numbersAsChars = from l in leftSequence
                     join r in rightSequence
                     on l equals (int)r into leftJoin
                     from result in leftJoin.DefaultIfEmpty('?')
                     select new
                     {
                         Number = l,
                         Character = result
                     };

foreach(var item in numbersAsChars)
{
    Console.WriteLine("Num = {0} ** Char = {1}", item.Number, item.Character);
}

ouput: 

Num = 99         Char = c
Num = 100        Char = d
Num = 5          Char = ?
Num = 20         Char = ?
Num = 102        Char = ?
Num = 105        Char = i

如果DefaultIfEmpty使用a(不指定默认值)并且将导致在正确的序列上没有匹配项,则必须确保null在访问其属性之前,该对象不在。否则将导致NullReferenceException。例:

var leftSequence = new List<int> { 1, 2, 5 };
var rightSequence = new List<dynamic>()
    {
        new { Value = 1 },
        new { Value = 2 },
        new { Value = 3 },
        new { Value = 4 },
    };

var numbersAsChars = (from l in leftSequence
                        join r in rightSequence
                        on l equalsr.Valueinto leftJoin
                        from result in leftJoin.DefaultIfEmpty()
                        select new
                        {
                            Left = l,
                            // 5右边没有匹配的对象,因此结果 
                            // 将等于null。 
                            // 为避免错误,请使用:
                            //    -C#6.0或更高版本-?。 
                            //    -欠结果== null?0:结果值
                            Right = result?.Value
                        }).ToList();