.NET 基礎-3

特性

數據契約

簡介:

  • 服務端和客戶端之間要傳送的自定義數據類型
  • 當應用於類型的成員時,指定該成員是數據協定的一部分並可由 DataContractSerializer 進行序列化。
  • 特性應用到的屬性必須同時具有 get 和 set 字段
  • 由成員返回的數據(即使是私有的)會進行序列化和反序列化,因此惡意用戶或進程可以查看或截獲這些數據。

例子

Types:
[DataContract]
public class File
{
    // excluded from serialization
    // does not have DataMemberAttribute
    public Guid Id { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public int Size { get; set; }
}
Usage:
File file = new File
{
    Id = Guid.NewGuid(),
    Name = "ImportantLegalDocuments.docx",
    Size = 50 * 1024
};

string json = JsonConvert.SerializeObject(file, Formatting.Indented);

Console.WriteLine(json);
// {
//   "Name": "ImportantLegalDocuments.docx",
//   "Size": 51200
// }
還可以轉換爲字典類型
 SortedDictionary<string, string> dicts = JsonConvert.DeserializeObject<SortedDictionary<string, string>>(JsonModel);

集合的選型

簡介

  • 開發過程中,我們都知道java對於集合總是使用hashmap。我在平常開發過程中一般都是list等,那麼關於集合我們怎麼選擇呢?類似的數據在作爲集合而存儲和操作時通常可以得到更高效地處理。

命名空間

  • system.Array
  • System.Collections
  • System.Collections.Generic
  • System.Collections.Concurrent
  • System.Collections.lmmutable

以上幾個集合的命名空間類主要作用這裏簡單介紹一下,與上面一一對應

  • 用於創建、處理、搜索數組並對數組進行排序,從而充當公共語言運行時中所有數組的基類
  • 接口和類定義各種對象(如列表、隊列、位數組、哈希表和字典)的集合。
  • 定義泛型集合的接口和類,用戶可以使用泛型集合來創建強類型集合,這種集合能提供比非泛型強類型集合更好的類型安全性和性能。
  • 提供多個線程安全集合類。當有多個線程併發訪問集合時,應使用這些類代替 System.Collections 和 System.Collections.Generic 命名空間中的對應類型。 但是,不保證通過擴展方法或通過顯式接口實現訪問集合對象是線程安全的,可能需要由調用方進行同步
  • 包含用於定義不可變集合的接口和類。

常用集合功能

實現集合的操作。可以直接或間接實現 ICollection 接口或 ICollection 接口,這些接口的集合均共享這些功能:

  • 可枚舉集合
    將枚舉器看作集合中可指向任何元素的可移動指針,可以使用
  • 可將集合內容複製到數組
    得到的數組始終是一維的,下限爲零
  • 容量和計數屬性
    當達到當前容量時,大多數的集合都會自動擴展容量。具體操作:重新分配內存並將元素從舊的集合複製都新的集合,這減少了要求使用集合的代碼;性能可能會收到不利影響。例如,對 List 來說,如果 Count 比 Capacity 少,那麼添加項就是一項 O(1) 操作。 如需增加容量以容納新元素,則添加項成爲 O(n) 操作,其中 n 是 Count。 避免因多次重新分配而導致的性能較差的最佳方式是:將初始容量設置爲集合的估計大小。
    BitArray 是一種特殊情況;它的容量與其長度相同,而其長度與其計數相同。
  • 下限一致
  • 同步以從多個線程進行訪問(僅 System.Collections 類)

集合複雜度

可變 複雜度最優 複雜度最壞 不可變 複雜度
Stack.Push O(1) O(n) ImmutableStack.Push O(1)
Queue.Enqueue O(1) O(n) ImmutableQueue.Enqueue O(1)
List.Add O(1) O(n) ImmutableList.Add O(log n)
List.Item[Int32] O(1) O(1) ImmutableList.Item[Int32] O(log n)
List.Enumerator O(n) O(n) ImmutableList.Enumerator O(n)
HashSet.Add, lookup O(1) O(n) ImmutableHashSet.Add O(log n)
SortedSet.Add O(log n) O(n) ImmutableSortedSet.Add O(log n)
Dictionary.Add O(1) O(n) ImmutableDictionary.Add O(log n)
Dictionary lookup O(1) O(1) -或者從嚴格意義上說,O(n) ImmutableDictionary lookup O(log n)
SortedDictionary.Add O(log n) O(n log n) ImmutableSortedDictionary.Add O(log n)

ImmutableList 在 for 循環內的效果較差。 使用 foreach 循環枚舉 ImmutableList 很有效,因爲 ImmutableList 使用二進制樹來存儲其數據,而不是像 List 那樣使用簡單數組。 數組可以非常快速地編入索引,但必須向下遍歷二進制樹,直到找到具有所需索引的節點。
此外,SortedSet 與 ImmutableSortedSet 的複雜性相同。 這是因爲它們都使用了二進制樹。 當然,顯著的差異在於 ImmutableSortedSet 使用不可變的二進制樹。 由於 ImmutableSortedSet 還提供了一個允許變化的 System.Collections.Immutable.ImmutableSortedSet.Builder 類,因此可以同時實現不可變性和保障性能。

如何選擇集合

順序列表(檢索元素值後就將該元素丟棄)

  • FIFO :Queue/ Queue/
  • LIFO :Stack 類或 Stack 泛型類
  • 多個線程進行安全訪問,ConcurrentQueue/ConcurrentStack
  • 不可變性, ImmutableQueue 和 ImmutableStack
  • LinkedList 泛型類允許從開頭到末尾或從末尾到開頭的順序訪問

按索引訪問每個元素

  • ArrayList 和 StringCollection 類以及 List 泛型類按從零開始的元素索引提供對其元素的訪問。 如果要獲得不可變性,請考慮不可變泛型版本 ImmutableArray 和 ImmutableList
  • Hashtable、SortedList、ListDictionary 和 StringDictionary 類以及 Dictionary<TKey,TValue> 和 SortedDictionary<TKey,TValue> 泛型類按元素的鍵提供對其元素的訪問。 此外,還有幾個相應類型的不可變版本:ImmutableHashSet、ImmutableDictionary<TKey,TValue>、ImmutableSortedSet 和 ImmutableSortedDictionary<TKey,TValue>。
  • NameObjectCollectionBase 和 NameValueCollection 類以及 KeyedCollection<TKey,TItem> 和 SortedList<TKey,TValue> 泛型類按從零開始的元素索引或元素的鍵提供對其元素的訪問。

每個元素都包含一個值、一個鍵和一個值的組合或一個鍵和多個值的組合

  • 一個值:使用任何基於 IList 接口或 IList 泛型接口的集合。 要獲得不可變選項,請考慮 IImmutableList 泛型接口。
  • 鍵值對:使用任何基於 IDictionary 接口或 IDictionary<TKey,TValue> 泛型接口的集合。 要獲得不可變選項,請考慮 IImmutableSet 或 IImmutableDictionary<TKey,TValue> 泛型接口。
  • 帶有嵌入鍵的值:使用 KeyedCollection<TKey,TItem> 泛型類。
  • 一個鍵和多個值:使用 NameValueCollection 類。

需要快速搜索和信息檢索

  • 對於小集合(10 項或更少),ListDictionary 速度比 Hashtable 快。 Dictionary<TKey,TValue> 泛型類提供比 SortedDictionary<TKey,TValue> 泛型類更快的查找。 多線程的實現爲 ConcurrentDictionary<TKey,TValue>。 ConcurrentBag 爲無序數據提供快速的多線程插入。

只接受字符串的集合

  • StringCollection(基於 IList)和 StringDictionary(基於 IDictionary)位於 System.Collections.Specialized 命名空間。
  • 此外,通過指定其泛型類參數的 String 類,可以使用 System.Collections.Generic 命名空間中的任何泛型集合類作爲強類型字符串集合。 例如,可以將變量聲明爲採用 List 或 Dictionary<String,String> 類型。

以與輸入方式不同的方式對元素進行排序

  • Hashtable 類按其哈希代碼對其元素進行排序。
  • SortedList 類以及 SortedList<TKey,TValue> 和 SortedDictionary<TKey,TValue> 泛型類按鍵對元素進行排序。 排序順序的依據爲,實現 SortedList 類的 IComparer 接口和實現 SortedList<TKey,TValue> 和SortedDictionary<TKey,TValue> 泛型類的 IComparer 泛型接口。 在這兩種泛型類型中,雖然 SortedDictionary<TKey,TValue> 的性能優於 SortedList<TKey,TValue>,但 SortedList<TKey,TValue> 佔用的內存更少。
  • ArrayList 提供了一種 Sort 方法,此方法採用 IComparer 實現作爲參數。 其泛型對應項(List 泛型類)提供一種 Sort 方法,此方法採用 IComparer 泛型接口的實現作爲參數。

泛型集合爲何比非泛型好

  • 泛型時不必對元素進行裝箱
  • 可獲得類型安全的自動化優點而無需從基集合類型派生和實現特定類型的成員

集合內的比較和排序

檢查相等

泛型:

  • 如果類型 T 實現 IEquatable 泛型接口,則相等比較器是該接口的 Equals 方法。
  • 如果類型 T 未實現 IEquatable,則使用 Object.Equals 。
    此外,字典集合的某些構造函數重載接受 IEqualityComparer 實現,用於比較鍵是否相等。

排序

- 如果類型 T 實現 System.IComparable<T> 泛型接口,則默認比較器是該接口的 IComparable<T>.CompareTo(T) 方法。
- 如果類型 T 實現非泛型 System.IComparable 接口,則默認比較器是該接口的 IComparable.CompareTo(Object) 方法。
- 如果類型 T 未實現任何接口,則沒有默認比較器,必須顯式提供一個比較器或比較委託。

爲了提供顯式比較,某些方法接受 IComparer 實現作爲參數。 例如, List.Sort 方法接受 System.Collections.Generic.IComparer 實現。
參考https://docs.microsoft.com/zh-cn/dotnet/standard/collections/hashtable-and-dictionary-collection-types
總結:一般處理幾百幾千數據除特殊要求外。List都夠用,具體可以參考我的多線程和代碼優化部分

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章