参考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992

1、集合set:纯粹的数据集合

2、线性结构:一对一的,数组

3、树形结构:一对多的,菜单/文件夹/类别/属性控件/表达式目录树

4、图形/网状结构:多对多,地图应用比较多,网站的应用比较少

线性结构:

Array/ArrayList/List/LinkedList/Queue/Stack/HastSet/SortedSet/Hashtable/SortedList/Dictionary/SortedDictionary

IEnumerable、ICollection、IList、IQueryable

接口是标机功能的,不同的接口岔开,就是为了接口隔离;虽然我们接口内容也可以复用。

IEnumerable任何数据集合,都实现了的,为不同的数据结构,提供了统一数据访问方式,这个就是迭代器模式。

1、内存连续存储,节约空间,可以索引访问,读取速度快,增删慢

  Array:在内存上连续分配的,而且元素类型是一样的。

 int[] intArray = new int[];
intArray[] = ;
string[] stringArray = new string[] { "", "" };//Array

  ArrayList:不定长的,连续分配的;元素没有类型限制,任何元素都是当成object处理,如果是值类型,会有装箱操作;读取快,增删慢。

 ArrayList arrayList = new ArrayList();
arrayList.Add("Bingle1");
arrayList.Add("Bingle2");
arrayList.Add();//add增加长度
//arrayList[4] = 26;//索引复制,不会增加长度
//删除数据
//arrayList.RemoveAt(4);
var value = arrayList[];
arrayList.RemoveAt();
arrayList.Remove("Bingle2");

  List<T>:也是Array,内存上都是连续拜访的;不定长;泛型,保证类型安全,避免装箱拆箱;读取快,增删慢。

List<int> intList = new List<int>() { , , ,  };
intList.Add();
intList.Add();
//intList.Add("123");
//intList[0] = 123;
List<string> stringList = new List<string>();
//stringList[0] = "123";//异常的
foreach (var item in intList)
{ }

2、非连续拜访的,存储数据+地址,找书的话就只能顺序查找,读取就比较慢,增删快

  LinkedList<T>:泛型的特点;链表,元素不连续分配,每个元素都有记录前后节点;节点值可以重复。能不能下标访问?不能的,找元素就只能遍历,查找不方便,增删就比较方便。

 LinkedList<int> linkedList = new LinkedList<int>();
//linkedList[3]
linkedList.AddFirst();
linkedList.AddLast(); bool isContain = linkedList.Contains();
LinkedListNode<int> node123 = linkedList.Find(); //元素123的位置 从头查找
linkedList.AddBefore(node123, );
linkedList.AddBefore(node123, );
linkedList.AddAfter(node123, ); linkedList.Remove();
linkedList.Remove(node123);
linkedList.RemoveFirst();
linkedList.RemoveLast();
linkedList.Clear();

  Queue:就是链表,先进先出,放任务延迟执行,A不断写入日志任务,B不断获取任务去执行

 Queue<string> numbers = new Queue<string>();
numbers.Enqueue("one");
numbers.Enqueue("two");
numbers.Enqueue("three");
numbers.Enqueue("four");
numbers.Enqueue("four");
numbers.Enqueue("five"); foreach (string number in numbers)
{
Console.WriteLine(number);
} Console.WriteLine($"Dequeuing '{numbers.Dequeue()}'");
Console.WriteLine($"Peek at next item to dequeue: { numbers.Peek()}");
Console.WriteLine($"Dequeuing '{numbers.Dequeue()}'"); Queue<string> queueCopy = new Queue<string>(numbers.ToArray());
foreach (string number in queueCopy)
{
Console.WriteLine(number);
} Console.WriteLine($"queueCopy.Contains(\"four\") = {queueCopy.Contains("four")}");
queueCopy.Clear();
Console.WriteLine($"queueCopy.Count = {queueCopy.Count}");

  Stack:就是链表,先进后出,解析表达式目录树的时候,先产生的数据后使用。操作记录为命令,撤销的时候是倒叙的。

 Stack<string> numbers = new Stack<string>();
numbers.Push("one");
numbers.Push("two");
numbers.Push("three");
numbers.Push("four");
numbers.Push("five");//放进去 foreach (string number in numbers)
{
Console.WriteLine(number);
} Console.WriteLine($"Pop '{numbers.Pop()}'");//获取并移除
Console.WriteLine($"Peek at next item to dequeue: { numbers.Peek()}");//获取不移除
Console.WriteLine($"Pop '{numbers.Pop()}'"); Stack<string> stackCopy = new Stack<string>(numbers.ToArray());
foreach (string number in stackCopy)
{
Console.WriteLine(number);
} Console.WriteLine($"stackCopy.Contains(\"four\") = {stackCopy.Contains("four")}");
stackCopy.Clear();
Console.WriteLine($"stackCopy.Count = {stackCopy.Count}");

  队列是没有底的瓶子,栈是有底的瓶子

  集合:纯粹的集合,容器,东西丢进去,唯一性,无序的。

  HashSet:hash分布,元素间没有关系,动态增加容量,去重的。统计用户IP;IP投票;交叉并补;二次好友/间接关注/粉丝集合

 HashSet<string> hashSet = new HashSet<string>();
hashSet.Add("");
hashSet.Add("");
hashSet.Add("");
hashSet.Add("");
hashSet.Add("");
hashSet.Add(""); HashSet<string> hashSet1 = new HashSet<string>();
hashSet1.Add("");
hashSet1.Add("");
hashSet1.Add("");
hashSet1.Add("");
hashSet1.Add("");
hashSet1.Add("");
hashSet1.SymmetricExceptWith(hashSet);//补
hashSet1.UnionWith(hashSet);//并
hashSet1.ExceptWith(hashSet);//差
hashSet1.IntersectWith(hashSet);//交

  SortSet:排序的集合;去重而且排序;统计排名,每统计一个就丢进去集合

 SortedSet<string> sortedSet = new SortedSet<string>();
//IComparer<T> comparer 自定义对象要排序,就用这个指定
sortedSet.Add("");
sortedSet.Add("");
sortedSet.Add("");
sortedSet.Add("");
sortedSet.Add("");
sortedSet.Add(""); SortedSet<string> sortedSet1 = new SortedSet<string>();
sortedSet1.Add("");
sortedSet1.Add("");
sortedSet1.Add("");
sortedSet1.Add("");
sortedSet1.Add("");
sortedSet1.Add("");
sortedSet1.SymmetricExceptWith(sortedSet);//补
sortedSet1.UnionWith(sortedSet);//并
sortedSet1.ExceptWith(sortedSet);//差
sortedSet1.IntersectWith(sortedSet);//交

  读取和增删都快的,有没有?有,hash散列,字典。是key-value,一段连续空间放value(开辟的空间比用到的多,hash使用空间换性能),基于key散列计算得到地址索引,这样读取快,但是没有数组快。增删也快,删除时也是计算位置,增加也不影响别人。代价就是,肯定会出现2个key(散列冲突),散列结果一致,可以让第二次的+1;可能会造成效率的降低,尤其是数据量大的情况下,以前测试Dictionary在3W条左右的时候,性能爱是下降的厉害。

  Hashtable---key-value,体积可以动态增加,拿着key计算下一个地址,然后放入key-value;object-装箱茶香,如果不同的key得到相同的地址,第二个在前面地址上+1;查找的时候,如果地址对应数据的key不对,那就+1查找。。

  浪费了空间,Hashtable是基于数组实现;查找个数据,一次定位;增删,一次定位;增删改查都很快,但是浪费空间,数据太多,重复定位定位,效率就下去了。

 Hashtable table = new Hashtable();
table.Add("", "");
table[] = ;
table[] = ;
table[] = ;
table[] = ;
table["eleven"] = ;
foreach (DictionaryEntry objDE in table)
{
Console.WriteLine(objDE.Key.ToString());
Console.WriteLine(objDE.Value.ToString());
}
//线程安全
Hashtable.Synchronized(table);//只有一个线程写 多个线程读

字典:泛型;key - value,增删查改 都很快;有序的。但是字段不是线程安全的,ConcurrentDictionary

 Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(, "HaHa");
dic.Add(, "HoHo");
dic.Add(, "HeHe");
dic.Add(, "HiHi");
dic.Add(, "HuHu1");
dic[] = "HuHu";
dic.Add(, "HuHu");
foreach (var item in dic)
{
Console.WriteLine($"Key:{item.Key}, Value:{item.Value}");
}

我们来看一下List,如下图

List集合为什么会继承这么多接口呢?

  1、ICollection:

    Count、IsReadOnly、Add、Clear、Contains、CopyTo、Clear

  2、IList:

    T this[int index] (索引)、IndexoOf、.....

  3、IEnumerable:

    遍历才会去查询比较,迭代器 yield

    GetEnumerator:Current、MoveNext、Reset

    任何数据集合,都实现了IEnumerable,为不同的数据结构提供了统一的数据访问方式,这个就是迭代器模式。

  4、IQueryable:

    表达式目录树的解析,延迟到遍历的时候才去执行,EF的延迟查询

    IQueryProvider Provider{get;}

    

yield是语法糖,编译时由编译器生成Iterrator的代码,包括movenext current  reset

  含有yield的函数说明它是一个生成器,而不是普通的函数。当程序运行到yield这一行时,该函数会返回值,并保存当前域的所有变量状态;等到该函数下一次被调用时,会从上一次中断的地方开始执行,一直遇到下一个yield, 程序返回值, 并在此保存当前状态; 如此反复,直到函数正常执行完成。

   迭代器模式是设计模式中行为模式(behavioral pattern)的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式。简单来说,迭代器模式使得你能够获取到序列中的所有元素 而不用关心是其类型是array,list,linked list或者是其他什么序列结构。这一点使得能够非常高效的构建数据处理通道(data pipeline)。

  --即数据能够进入处理通道,进行一系列的变换,或者过滤,然后得到结果。事实上,这正是LINQ的核心模式。

  在.NET中,迭代器模式被IEnumerator和IEnumerable及其对应的泛型接口所封装。如果一个类实现了IEnumerable接 口,那么就能够被迭代;调用GetEnumerator方法将返回IEnumerator接口的实现,它就是迭代器本身。迭代器类似数据库中的游标,他是 数据序列中的一个位置记录。迭代器只能向前移动,同一数据序列中可以有多个迭代器同时对数据进行操作。

下面是一个yield的一个简单Demo:

public class YieldShow
{
public IEnumerable<int> CreateEnumerable()
{
try
{
Console.WriteLine("{0} CreateEnumerable()方法开始", DateTime.Now);
for (int i = ; i < ; i++)
{
Console.WriteLine("{0}开始 yield {1}", DateTime.Now, i);
yield return i;
Console.WriteLine("{0}yield 结束", DateTime.Now);
if (i == )
{
yield break;//直接终结迭代 4会出现的,,
}
}
Console.WriteLine("{0} Yielding最后一个值", DateTime.Now);
yield return -;
Console.WriteLine("{0} CreateEnumerable()方法结束", DateTime.Now);
}
finally
{
Console.WriteLine("停止迭代!");
}
}
IEnumerable<int> iterable = this.CreateEnumerable();//1 不会直接执行
//IEnumerator iterator = iterable.GetEnumerator();
IEnumerator<int> iterator = iterable.GetEnumerator();
Console.WriteLine("开始迭代");
while (true)
{
Console.WriteLine("调用MoveNext方法……");
Boolean result = iterator.MoveNext();//2 正式开启CreateEnumerable
Console.WriteLine("MoveNext方法返回的{0}", result);
if (!result)
{
break;
}
Console.WriteLine("获取当前值……");
Console.WriteLine("获取到的当前值为{0}", iterator.Current);
}
public class YieldDemo
{
public IEnumerable<int> Power()
{
for (int i = ; i < ; i++)
{
yield return this.Get(i); //Console.WriteLine("这里再来一次");
//yield return this.Get(i) + 1;
}
} public IEnumerable<int> Common()
{
List<int> intList = new List<int>();
for (int i = ; i < ; i++)
{
intList.Add(this.Get(i));
}
return intList;
} private int Get(int num)
{
Thread.Sleep();
return num * DateTime.Now.Second;
}
} YieldDemo yieldDemo = new YieldDemo();
foreach (var item in yieldDemo.Power())
{
Console.WriteLine(item);//按需获取,要一个拿一个
if (item > )
break;
}
Console.WriteLine("*******************************************");
foreach (var item in yieldDemo.Common())
{
Console.WriteLine(item);//先全部获取,然后一起返还
if (item > )
break;
}

dynamic关键字:

  .NET Framework4.0出现的,让程序有了弱类型的特点;

  强类型特点:

    编译时完成安全检查

  弱类型:

    运行时才检查类型

 object A = new YieldDemo();
//A.Power();
Type type = A.GetType();
MethodInfo method = type.GetMethod("Power");
method.Invoke(A, null); dynamic dA = A;
dA.Power();
//1 代替反射 2 数据绑定方便 3 跟C++交互方便
//性能比反射高
dynamic str = "abcd";//任何跟dynamic交互,都变成dynamic
Console.WriteLine(str.Length);
Console.WriteLine(str.Substring());

数据类型和特殊类型-C#的更多相关文章

  1. 由js apply与call方法想到的js数据类型(原始类型和引用类型)

    原文地址:由js apply与call方法想到的js数据类型(原始类型和引用类型) js的call方法与apply方法的区别在于第二个参数的不同,他们都有2个参数,第一个为对象(即需要用对象a继承b, ...

  2. MySQL日期数据类型、时间类型使用总结

    MySQL日期数据类型.时间类型使用总结 MySQL日期数据类型.MySQL时间类型使用总结,需要的朋友可以参考下.   MySQL 日期类型:日期格式.所占存储空间.日期范围 比较. 日期类型    ...

  3. ABAP基本数据类型、通用类型

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  4. MySQL数据库数据类型之集合类型SET测试总结

    MySQL数据库提供针对字符串存储的一种特殊数据类型:集合类型SET,这种数据类型可以给予我们更多提高性能.降低存储容量和降低程序代码理解的技巧,前面介绍了首先介绍了四种数据类型的特性总结,其后又分别 ...

  5. Delphi 基本数据类型列表 高级数据类型列表 字符类型查询列表清单

    原文:Delphi 基本数据类型列表 高级数据类型列表 字符类型查询列表清单 长长的列表文字类型文件 分类 范围 字节 备注 简单类型 序数 整数 Integer -2147483648 .. 214 ...

  6. MySQL (二)-- 数据类型(列类型)、数值类型、 小数类型、 时间日期类型、 字符串类型 、 MySQL记录长度、列属性

    1 数据类型(列类型) 所谓的数据类型:对数据进行统一的分类,从系统的角度出发是为了能够使用统一的方式进行管理,更好的利用有限的空间. SQL中将数据类型分成了三大类: 2 数值类型 数值类型数据:都 ...

  7. redis数据类型-散列类型

    Redis数据类型 散列类型 Redis是采用字典结构以键值对的形式存储数据的,而散列类型(hash)的键值也是一种字典结构,其存储了字段(field)和字段值的映射,但字段值只能是字符串,不支持其他 ...

  8. Mysql 数据类型、约束类型

    mysql数据类型 MySQL中定义数据字段的类型对你数据库的优化是非常重要的. MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型.   数值类型 MySQL支持所有标准 ...

  9. go数据类型之基本类型

    基本数据类型 数值型 整数 int 64位操作系统默认为int64,32位操作系统为int32,但是类型检查时时int int8 (byte 1字节) int16 (short 2字节) int32 ...

  10. Java基础之基本数据类型的包装类型

    Java的基本数据类型的包装数据类型有多种: int Integer,short Short,boolean Boolean,float Float,double Double等等. Java包装类数 ...

随机推荐

  1. Thinkphp <= 5.0.10 缓存getshell复现

    目录 Thinkphp <= 5.0.10 缓存getshell复现 0x01 poc 0x02 跟踪源码 0x03 审计思路 0x04 补丁 0x05 参考 Thinkphp <= 5. ...

  2. ASP.NET Core - 基于IHttpContextAccessor实现系统级别身份标识

    问题引入: 通过[ASP.NET Core[源码分析篇] - 认证]这篇文章中,我们知道当请求通过认证模块时,会给当前的HttpContext赋予当前用户身份标识,我们在需要授权的控制器中打上[Aut ...

  3. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之二 || 后端项目搭建

    本文梯子 前言 1..net core 框架性能测试 2..net core 执行过程 3.中间件执行过程 4.AOP切面 5.整体框架结构与数据库表UML 一.创建第一个Core 1.SDK 安装 ...

  4. SVN 回滚提交的代码

    有的时候,代码提交错了,我们可以通过SVN回滚到指定的版本,然后在提交回滚后的代码,即为撤销提交. 回滚代码 重新提交刚才回滚后的代码

  5. Violet音乐社区设计文档

    目录 Violet音乐社区设计文档 一.引言 1.1 编写目的 1.2 开发背景 二.用例图设计 2.1游客实例设计 2.2 管理员实例设计 2.3 普通用户实例设计 三.类图设计 3.1 歌手类 3 ...

  6. 037.[转] springboot 配置多个数据源

    1.在application.properties文件 配置两个数据源 #默认使用 tomcat-jdbc spring.datasource.type=org.apache.tomcat.jdbc. ...

  7. C# 中使用 Redis 简单存储

    Redis 是一个开源的使用 ANSI C语言编写的支持网络.可基于内存也可持久化的日志型.Key-Value 数据库. 常用它来存储缓存数据,能非常轻松的实现缓存过期刷新机制. 多种语言都可以连接到 ...

  8. Checklist for an RMAN Restore (Doc ID 1554636.1)

    Checklist for an RMAN Restore (Doc ID 1554636.1) APPLIES TO: Oracle Database - Enterprise Edition - ...

  9. 面向对象程序设计(JAVA) 第14周学习指导及要求

    2019面向对象程序设计(Java)第14周学习指导及要求 (2019.11.29-2019.12.2)   学习目标 (1)掌握GUI布局管理器用法: (2)掌握Java Swing文本输入组件用途 ...

  10. 如何在Markdown格式下插入动图/gif

    上传GIF动图与上传普通图片是一样的,都需要以下在markdown语法中 ![]() 的小括号内填写图片的地址.问题在于如何获取本地gif的地址呢? 核心的东西就是要把这个gif动图传上网络,这样图片 ...