C# 是否使用.DefaultIfEmpty()而不是.FirstOrDefault()??字符串。空;

C# 是否使用.DefaultIfEmpty()而不是.FirstOrDefault()??字符串。空;,c#,linq,C#,Linq,我如何集成.DefaultIfEmpty()扩展方法,以便使用而不是 .FirstOrDefault() ?? String.Empty; 代码: 您可以使用: var query = ...; return query.DefaultIfEmpty(string.Empty).First(); 但这并不能降低IMO的复杂性。如果您对扩展方法感兴趣,那么您可以使用以下方法: public static class Helpers { public static string Fir

我如何集成
.DefaultIfEmpty()
扩展方法,以便使用而不是

.FirstOrDefault() ?? String.Empty;
代码:

您可以使用:

var query = ...;

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

但这并不能降低IMO的复杂性。

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

public static class Helpers
{
    public static string FirstOrEmpty(this IEnumerable<string> source)
    {
        return source.FirstOrDefault() ?? string.Empty;
    }
}
公共静态类帮助程序
{
公共静态字符串FirstOrEmpty(此IEnumerable源)
{
返回source.FirstOrDefault()??string.Empty;
}
}
编辑

此方法不是通用的,因为这样我们就必须使用
default(t)
,它将为我们提供
null
而不是
string。空的

代码:

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();
对于
DefaultIfEmpty
FirstOrDefault
的语义含义的怀疑,以下是从库中反编译的代码:

  • 代码

    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);
    }
    
    public静态IEnumerable DefaultIfEmpty(此IEnumerable源)
    {
    返回source.DefaultIfEmpty(默认值(TSource));
    }
    公共静态IEnumerable DefaultIfEmpty(此IEnumerable源,TSource defaultValue)
    {
    if(source==null)
    {
    抛出错误。ArgumentNull(“源”);
    }
    返回DefaultIfEmptyInterator(源,defaultValue);
    }
    公共静态TSource优先(此IEnumerable源)
    {
    if(source==null)
    {
    抛出错误。ArgumentNull(“源”);
    }
    IList list=源作为IList;
    如果(列表!=null)
    {
    如果(list.Count>0)
    {
    返回列表[0];
    }
    }
    其他的
    {
    使用(IEnumerator enumerator=source.GetEnumerator())
    {
    if(枚举数.MoveNext())
    {
    返回枚举数.Current;
    }
    }
    }
    抛出错误。NoElements();
    }
    公共静态TSource FirstOrDefault(此IEnumerable源)
    {
    if(source==null)
    {
    抛出错误。ArgumentNull(“源”);
    }
    IList list=源作为IList;
    如果(列表!=null)
    {
    如果(list.Count>0)
    {
    返回列表[0];
    }
    }
    其他的
    {
    使用(IEnumerator enumerator=source.GetEnumerator())
    {
    if(枚举数.MoveNext())
    {
    返回枚举数.Current;
    }
    }
    }
    返回默认值(TSource);
    }
    
这里有几点值得一提:

  • DefaultIfEmpty
    有一个无参数重载,它使用
    default(TSource)
    调用参数化重载并返回其结果

  • 无参数的
    FirstOrDefault
    First
    之间唯一的区别是后者在集合为空时抛出

    有关更多信息,请参阅MSDN上的

  • FirstOrDefault
    语义表达的
    first或default
    ,即所谓的;它不是第一个命名的
    ,也不是null
    。在c#中,引用类型的
    default(T)
    为null,但对于非引用类型,则不是。例如,
    default(int)
    为零

    关键字
    default
    从未在语义上表示为null。它是默认的

    另外,有关更多信息,请参阅MSDN


  • 我发现这门关于PluralSight的课程很有趣,当我看到这个问题时,我记起了它

    您可以观看整个过程,但是Map Reduce和
    选项
    策略(尤其是使用DefaultIfEmpty)似乎非常适合您的用例

    .NET中的战术设计模式:控制流 作者:佐兰·霍瓦特

    就个人而言,我不会
    DefaultIfEmpty
    感兴趣的是可枚举项,而不是标量值。创建您自己的扩展方法,可能也被命名为
    FirstOrDefault
    ,它使用
    T
    参数指定为默认值。然后可能
    T FirstOrEmpty(此IEnumerable源代码)
    @Ilya Ivanov,如果它是泛型的,则字符串的默认值仍然为null。但是
    T FirstOrDefault(此IEnumerable源代码,T默认值)
    是可能的。然后,再次使用
    .FirstOrDefault(string.Empty)
    vs.
    .FirstOrDefault()?string.Empty
    并没有多大区别。@hvd,我不得不承认这是我的第一个想法,但在那之后,我决定
    FirstOrEmpty
    可以提供更清晰的输出代码。是的,降低复杂性是我的目标之一。到目前为止,你还有什么其他建议吗?嗨,2k先生。现在你实际上是14k!我转到了你的解决方案。它不会用LINQ转换为实体。它将失败:“方法‘第一’只能用作最终的查询操作。请考虑在该实例中使用方法‘FrrStRealDebug’代替。”我最近不得不替换<代码> Debug TimeType()。
    ,这应该会得到相同的结果。@Triynko在OP的情况下,它可以正常工作,因为这些操作是最终的查询操作。如果您尝试在子查询中使用它们,则会出现异常。对于这个问题,当序列没有结果时,所需的输出是空字符串-而不是null,因此ken2k的答案是正确的。您的第一个问题是OrDefault();结尾没有意义。如果您期望OrDefault为空值,则序列为空。然后将返回“”,我建议是。First()相反。@Elisa:是的,它们在这里是一样的,因为我只是从你的代码中复制而没有更改,但我认为这并不重要。这很重要。使用FirstOrDefault只有50%的正确率。OrDefault(空值)永远不会发生,并且给读者一个错误的印象,代码在做什么。当然,空值只是“OrDefault”/非值类型(如integer)的默认值。感谢您的修订。1票赞成。以上注释的更正:“…非值类型(如integer)的默认值”。
    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);
    }