.NET 基础-3

简介: 服务端和客户端之间要传送的自定义数据类型
  • 服务端和客户端之间要传送的自定义数据类型
  • 当应用于类型的成员时,指定该成员是数据协定的一部分并可由 DataContractSerializer 进行序列化。
  • 特性应用到的属性必须同时具有 get 和 set 字段
  • 由成员返回的数据(即使是私有的)会进行序列化和反序列化,因此恶意用户或进程可以查看或截获这些数据。

例子

Types: [DataContract]publicclassFile{     // excluded from serialization    // does not have DataMemberAttribute    public Guid Id { get; set; }     [DataMember]     publicstring Name { get; set; }     [DataMember]     publicint 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);

2|0集合的选型

2|1简介

  • 开发过程中,我们都知道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 类,因此可以同时实现不可变性和保障性能。

2|2如何选择集合

顺序列表(检索元素值后就将该元素丢弃)

  • 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 泛型接口的实现作为参数。

2|3泛型集合为何比非泛型好

  • 泛型时不必对元素进行装箱
  • 可获得类型安全的自动化优点而无需从基集合类型派生和实现特定类型的成员

2|4集合内的比较和排序

检查相等

泛型:

  • 如果类型 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都够用,具体可以参考我的多线程和代码优化部分

相关文章
|
10月前
|
机器学习/深度学习 存储 量子技术
诺奖得主哈萨比斯新作登Nature,AlphaQubit解码出更可靠量子计算机
诺贝尔生物学奖得主德米斯·哈萨比斯团队在《自然》杂志发表突破性研究,开发出基于神经网络的量子错误解码器AlphaQubit。该解码器通过学习表面码显著提升量子计算机的可靠性和性能,特别是在处理量子比特脆弱性问题上表现出色。实验表明,AlphaQubit在不同代码距离上均超越现有解码器,为量子计算的实际应用带来希望。然而,其训练数据有限及计算复杂性高仍是挑战。
346 104
|
存储 API C语言
|
JavaScript IDE 开发工具
【VsCode+LeetCode】优雅玩法
【VsCode+LeetCode】优雅玩法
482 0
Ubuntu20.04安装fcitx后无法使用ibus的拼音输入法问题(配置完ibus重启之后还是用不了)
Ubuntu20.04安装fcitx后无法使用ibus的拼音输入法问题(配置完ibus重启之后还是用不了)
|
开发者 Apache 程序员
揭秘Apache Wicket:页面生命周期背后的神秘力量!
【8月更文挑战第31天】李工是一位热爱Web开发的程序员,近日在技术博客上分享了他对Apache Wicket框架的学习心得,特别是页面生命周期的理解。他认为掌握Wicket页面生命周期对于开发富交互式Web应用至关重要。他通过一个简单的计数器应用示例,详细解释了Wicket的组件化设计理念以及页面和组件在生命周期中的变化。
147 0
A-B罗克韦尔 2711-K10G9L1 标准型操作员终端
A-B罗克韦尔 2711-K10G9L1 标准型操作员终端
|
安全 测试技术 Python
软件测试面试题及答案,这个题库有3千多道最新面试真题可以刷
相信对于很多软件测试新手来说,技术项目的面试是十分让人头疼的,生怕没回答得好,就会跟这个offer失之交臂
371 0
|
JavaScript 前端开发
js时间转化为几天前,几小时前,几分钟前
js时间转化为几天前,几小时前,几分钟前
340 0
|
Java C语言 C++
C++_pair
pair是将2个数据组合成一组数据,当需要这样的需求时就可以使用pair,如stl中的map就是将key和value放在一起来保存。另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair。pair的实现是一个结构体,主要的两个成员变量是first second 因为是使用struct不是class,所以可以直接使用pair的成员变量。就算其他的语言中没有pair,比如java与c语言,也可以自己理解原理之后,通过结构体自己做一个。
235 0
C++_pair
|
JavaScript 中间件 数据中心