如何整合.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;
答案 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();
由于怀疑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);
}
这里有一点需要提及:
DefaultIfEmpty
具有无参数重载,它使用default(TSource)
调用参数化重载并返回其结果。
无参数FirstOrDefault
和First
之间的唯一区别是后者在集合为空时会抛出。
有关详细信息,请参阅MSDN上的Enumerable.FirstOrDefault<TSource> Method。
FirstOrDefault
语义表达first or default
,所谓的;它没有命名为first or null
。在c#中,引用类型的default(T)
是 null ,但对于非引用类型,它不是。例如,default(int)
为零。
关键字default
从未在语义上说过 null 。这是 DEFAULT 。
另外,有关详细信息,请参阅MSDN上的default Keyword。