14

如何集成.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

5 回答 5

18

你可以使用:

var query = ...;

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

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

于 2013-04-03T08:09:52.743 回答
6

如果你对扩展方法感兴趣,那么你可以使用这样的东西:

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

编辑

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

于 2013-04-03T08:11:30.437 回答
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

于 2016-01-07T14:16:23.737 回答
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();

DefaultIfEmpty由于对and语义的怀疑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);
    }
    

这里有一点需要提一下:

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

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

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

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

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

    此外,有关详细信息,请参阅MSDN 上的默认关键字

于 2013-04-03T08:39:21.247 回答
0

.NET 6 引入了能够传入默认值的概念,如果找不到该项目。例如,此代码现在在 .NET 6 中有效:

source.FirstOrDefault(String.Empty);

或者:

List<int> numbers = new List<int>();
var custom = numbers.FirstOrDefault(-1);

在上面的示例中,我们不再需要依赖于返回 0,这是 int 的默认值。当 0 在使用数字列表的上下文中是有效数字时,这可能很方便,而 -1 不是。

你可以阅读更多:

https://dotnetcoretutorials.com/2021/09/02/linq-ordefault-enhancements-in-net-6/ https://adamstorr.azurewebsites.net/blog/default-your-firstordefault-in-net6.0

于 2021-11-27T11:36:26.140 回答