使用.DefaultIfEmpty()而不是.FirstOrDefault()??的String.Empty;

时间:2013-04-03 08:05:24

标签: c# linq

如何整合.DefaultIfEmpty()扩展方法,以便我来使用

.FirstOrDefault() ?? String.Empty;

代码:

(from role in roleList
let roleArray = role.RoleId.Split(new char[] { WorkflowConstants.WorkflowRoleDelimiter })
where roleArray.Length.Equals(_SplittedRoleIdArrayLength) && 
      HasAccessToCurrentUnit(roleArray[_UnitIndexInRoleId])
select roleArray[_LevelIndexInRoleId]).FirstOrDefault() ?? String.Empty;

4 个答案:

答案 0 :(得分:14)

您可以使用:

var query = ...;

return query.DefaultIfEmpty(string.Empty).First();

但这并没有降低IMO的复杂性。

答案 1 :(得分:6)

如果您对扩展方法感兴趣,那么您可以使用以下内容:

public static class Helpers
{
    public static string FirstOrEmpty(this IEnumerable<string> source)
    {
        return source.FirstOrDefault() ?? string.Empty;
    }
}

修改

此方法不是通用的,因为我们必须使用default(T),它会给我们null而不是string.Empty

答案 2 :(得分:2)

我发现这个关于PluralSight的课程很有趣,当我看到这个问题时我记得它。

您可以观看整个课程,但Map Reduce和Option<T>策略尤其是使用DefaultIfEmpty似乎可能非常适合您的用例。

.NET中的战术设计模式:控制流程 作者:Zoran Horvat https://app.pluralsight.com/library/courses/tactical-design-patterns-dot-net-control-flow/table-of-contents

答案 3 :(得分:1)

代码:

var query=(
    from role in roleList
    let delimiter=WorkflowConstants.WorkflowRoleDelimiter
    let roleArray=role.RoleId.Split(new char[] { delimiter })
    where roleArray.Length.Equals(_SplittedRoleIdArrayLength)
    where HasAccessToCurrentUnit(roleArray[_UnitIndexInRoleId])
    select roleArray[_LevelIndexInRoleId]
    ).DefaultIfEmpty("").FirstOrDefault();

由于怀疑DefaultIfEmptyFirstOrDefault的语义含义,以下是从库中反编译的代码:

  • 代码

    public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source)
    {
        return source.DefaultIfEmpty<TSource>(default(TSource));
    }
    
    public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, TSource defaultValue)
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        return DefaultIfEmptyIterator<TSource>(source, defaultValue);
    }
    
    public static TSource First<TSource>(this IEnumerable<TSource> source)
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        IList<TSource> list = source as IList<TSource>;
        if (list != null)
        {
            if (list.Count > 0)
            {
                return list[0];
            }
        }
        else
        {
            using (IEnumerator<TSource> enumerator = source.GetEnumerator())
            {
                if (enumerator.MoveNext())
                {
                    return enumerator.Current;
                }
            }
        }
        throw Error.NoElements();
    }
    
    public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source)
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        IList<TSource> list = source as IList<TSource>;
        if (list != null)
        {
            if (list.Count > 0)
            {
                return list[0];
            }
        }
        else
        {
            using (IEnumerator<TSource> enumerator = source.GetEnumerator())
            {
                if (enumerator.MoveNext())
                {
                    return enumerator.Current;
                }
            }
        }
        return default(TSource);
    }
    

这里有一点需要提及:

  1. DefaultIfEmpty具有无参数重载,它使用default(TSource)调用参数化重载并返回其结果。

  2. 无参数FirstOrDefaultFirst之间的唯一区别是后者在集合为空时会抛出。

    有关详细信息,请参阅MSDN上的Enumerable.FirstOrDefault<TSource> Method

  3. FirstOrDefault语义表达first or default,所谓的;它没有命名为first or null。在c#中,引用类型的default(T) null ,但对于非引用类型,它不是。例如,default(int)为零。

    关键字default从未在语义上说过 null 。这是 DEFAULT

    另外,有关详细信息,请参阅MSDN上的default Keyword