![](/img/trans.png)
[英]In C#, should I use string.Empty or String.Empty or "" to intitialize a string?
[英]Use .DefaultIfEmpty() instead of .FirstOrDefault() ?? String.Empty;
如何集成.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;
你可以使用:
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;
}
}
編輯
這個方法不是通用的,因為那時我們必須使用default(T)
,它會給我們null
而不是string.Empty
。
我發現這個關於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
編碼:
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>方法 。
FirstOrDefault
語義表達為first or default
,因此被稱為; 它沒有被命名為first or null
。 在c#中,引用類型的default(T)
為null ,但對於非引用類型,則不是。 例如, default(int)
為零。
關鍵字default
在語義上從未說過null 。 這是默認的 。
此外,有關更多信息,請在MSDN上使用默認關鍵字 。
.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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.