.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 接口,这些接口的集合均共享这些功能: java

  • 可枚举集合
    将枚举器看做集合中可指向任何元素的可移动指针,可使用
  • 可将集合内容复制到数组
    获得的数组始终是一维的,下限为零
  • 容量和计数属性
    当达到当前容量时,大多数的集合都会自动扩展容量。具体操做:从新分配内存并将元素从旧的集合复制都新的集合,这减小了要求使用集合的代码;性能可能会收到不利影响。例如,对 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 类,所以能够同时实现不可变性和保障性能。
json

如何选择集合

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

  • 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都够用,具体能够参考个人多线程和代码优化部分
安全

相关文章
相关标签/搜索