出于好奇,!=null、Count > 0 和 .Any() 之間的根本區別是什么,以及何時使用它們的最佳時間?- 對于建筑和性能。
我知道 .Any() 用于 IEnumerables,而不是串列,但我發現自己在允許的情況下可以互換使用它們(!=null 和 Count > 0)。如果這是不好的做法,我不想養成這種習慣。
uj5u.com熱心網友回復:
作業方式Enumerable.Any如下
public static bool Any<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
throw Error.ArgumentNull(nameof (source));
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
// Returns very early if there are any items
if (enumerator.MoveNext())
return true;
}
return false;
}
有一些開銷,但實際上并沒有那么多,因此我假設它的Any()性能與List<T>.Count(IEnumerable擴展試圖回退到該值,因此這也應該是可比較的)。
清晰度方面,它最終歸結為品味問題。就我個人而言,我喜歡 的表現力Any(),因為它對我來說更接近自然語言。
rows.Any()
讓我想不到
rows.Count == 0
但不是那么多。
null比較以完全不同的方式作業。如果您不清楚這一點,您應該了解 C# 中的值和參考型別(警告null:最近情況有所不同,因為在當前版本的 C#/.NET 中默認情況下不允許值型別)。
總結:參考型別的存盤方式不同,實際變數(有點)只是指向資料存盤位置的指標(不是 100% 準確)。C 中的經典指標可以采用該值0來指示它們指向的資料不存在,該值被(至少作為一個概念)傳遞給 C#(以及其他類似 C 的語言,如 Java)。無論如何,由于在 C# 中不直接訪問指標,null因此發明了該變數以指示該變數不指向實際資料(“沒有與該變數關聯的資料”)。因此,比較List<int>變數null意味著您詢問是否已經創建了串列實體,這是必要的,但對于存盤的實際串列項來說不是足夠的標準。
uj5u.com熱心網友回復:
這取決于你的目標。AList不能為空,但有Count == 0。怎么樣Any()- 以 LINQ 風格使用它,例如:
if(MyEnumerable.Any(x => x.Id == myId))
{
// do something
}
uj5u.com熱心網友回復:
!=null
檢查串列是否為空。這可能代表也可能不代表與“無專案”相同的東西。我建議完全避免使用 null 作為串列,因為含義不清楚。使用一個空集合來表示“沒有專案”。如果您需要其他東西來表示“不存在”,請使用可能/可選型別,或者如果默認情況下它們不可為空,則使用可能為空的參考。這應該是給讀者一個更清晰的信號,“沒有專案”和“不存在”是不同的狀態,可能需要以不同的方式處理。
.Any()
這是 LINQ 的一部分,因此適用于任何可列舉的集合。它非常清晰和方便,但會比檢查屬性稍慢。但如果您想檢查某些特定值的存在,它允許行內過濾。
.Count > 0 or .Length > 0
這僅適用于具有 Count/Length 屬性的集合,但應該是最快的,因為它只是進行比較。至少假設屬性很簡單并且不會做很多作業。
但請注意,除非您非常頻繁地運行代碼,否則性能問題并不是很重要。因此,在嘗試進行任何優化之前先測量性能。
uj5u.com熱心網友回復:
TL;DR:如果集合型別實作它Any(),實際上會呼叫它。ICollection.Count否則,它將嘗試選擇檢查集合是否為非空的“最佳”方式。
檢查null與檢查空是完全不同的,將它與空檢查進行比較并沒有任何意義。
Paul Kertscher 已經回答了您的問題的實質,但是為了幫助將來對此類事情進行查詢,值得記住的是,dotnet 的源代碼實際上可以在線獲得。
Any()例如,可以在此處找到LINQ 方法的代碼: https ://github.com/dotnet/runtime/blob/main/src/libraries/System.Linq/src/System/Linq/AnyAll.cs (和運行時 repo 的其余部分還有很多,這里有庫)。它比保羅在他的答案中包含的方法版本稍微復雜一點......可能他正在參考不同版本的運行時。這是最新的實作(原始來源中的評論):
public static bool Any<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
if (source is ICollection<TSource> collectionoft)
{
return collectionoft.Count != 0;
}
else if (source is IIListProvider<TSource> listProv)
{
// Note that this check differs from the corresponding check in
// Count (whereas otherwise this method parallels it). If the count
// can't be retrieved cheaply, that likely means we'd need to iterate
// through the entire sequence in order to get the count, and in that
// case, we'll generally be better off falling through to the logic
// below that only enumerates at most a single element.
int count = listProv.GetCount(onlyIfCheap: true);
if (count >= 0)
{
return count != 0;
}
}
else if (source is ICollection collection)
{
return collection.Count != 0;
}
using (IEnumerator<TSource> e = source.GetEnumerator())
{
return e.MoveNext();
}
}
的代碼ICollection是 System.Collection的一部分,并且IListProvider是System.Linq的一部分。
您可以看到有多種方法Any()可以測驗底層集合中是否包含任何專案,并且您可以合理地假設它們是按照速度/效率的順序進行嘗試的。顯然,您可以撰寫一個非常糟糕的ICollection.Count { get }. (順便說一下,陣列ICollection.Count通過顯式介面實作,該介面將其映射到它們的屬性Length,這就是為什么Any()不需要關心檢查的原因Length)
我還沒有查找 , 的任何實作IListProvider<T>.GetCount。介面方法的檔案是這樣說的:
如果為真,則僅當這樣做很快(確定或可能是恒定時間)時才應計算計數,否則應回傳 -1。
同樣,可能存在可怕的實作,但可能不存在。
使用Any()而不是Count. 呼叫方法和運行一些 if 和強制轉換的額外開銷通常可以忽略不計。只需確保不要與 confise 混淆Count,Count()因為后者可能需要遍歷整個集合,這可能是一件相對昂貴且耗時的事情,如果您只想檢查空虛,那將毫無意義。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/477245.html
