数组: 数组 ,他可以存储相同类型的固定数量的数据,可以通过索引取得相应的值。
如果存储的是值类型的话:比如 int[] arr=new int[2]; 那么变量arr 在栈上 ,他引用 两个 托管堆上的 int 值。
如果存储的是引用类型:比如 Person[] arr=new Person[2]; 那么 变量 arr、在栈上,这个变量引用了 用来存储 托管堆上person类的引用的数组。
Array 类: 是一个抽象类,他实现了 ICloneable, IList, ICollection, IEnumerable 这几个接口
拷贝:
而ICloneable 实现了Clone() 他是创建一个浅表层的副本: 如果是 值类型,他复制的东西是 所有的值。 如果是应用类型,它复制的是 引用,新的数组操作的 还是 同一个内存。
Copy 同样是浅拷贝,区别就是:Clone 直接创建一个新的数组,Copy 要有相同维数 , 和足够多的容量 存储拷贝。
需要深拷贝 引用类型数组的话, 要迭代 数组创建新的对象。
排序: Array 类使用 快排算法 对数组中的元素进行排序, Sort()方法要求 数组中的元素实现IComparable接口 。Array.Sort(strings),简单类型String int32 实现了这个借口。
IComparable接口一个 CompareTo() ,要使用sort() 要实现它,相等返回 0 , 如果 实例排在参数 前面 方法返回小于0的数, 实例排在参数后面 返回大于 0 的参数。 如果 要实现别的排序方式 可以实现 IComPare接口 ,和或 Icompare<T> 接口, IcomPare类独立于 要比较的类 这样就可以通过 Array.Sort(persons,new PersonCompare)进行比较了.
IEunmerator 接口: 枚举接口,GetEnumerator()方法 ,返回一个实现 IEunmerator 接口的的 枚举,他定义了了
bool MoveNext();
object Current { get; }
void Reset();
三个方法。
foreach 使用了 枚举
而使用 yield 迭代 会方便创建 枚举器,
public class Gge
{
//实现
GetEnumerator()
public IEnumerator<String> GetEnumerator() { yield return 9; yield return 6; } }
就可以使用foreach 迭代 Gge了。
包含 yield 语句的 方法 或 属性 称为 迭代块 必须返回 IEnumerator、或Ienumerable 接口 ,编译时yield语句会生成一个枚举器。
通过使用 yield 定义迭代器,可在实现自定义集合类型的 IEnumerable 和IEnumerator 模式时无需其他显式类(保留枚举状态的类,有关示例,请参阅IEnumerator<T>)。
public class PowersOf2 { static void Main() { // Display powers of 2 up to the exponent of 8: foreach (int i in Power(2, 8)) { Console.Write("{0} ", i); } } public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent) { int result = 1; for (int i = 0; i < exponent; i++) { result = result * number; yield return result; } } // Output: 2 4 8 16 32 64 128 256 }
使用 迭代块 编译器会生成 一个yield 类型,其中包含一个状态机、、待完善。
集合 : 数组大小是固定的 , 如果要 要存储动态元素个数 就要使用集合。集合类 有List<T> ,队列 ,栈, 链表 ,字典 ,集。 分泛型类集合有 ArrayList HashTable. 线程安全的集合类 位于 System.Conllection.Concurrent。
动态列表有List<T > 实现了 IList , ICollection, IEnumerable , IList<T> , ICollection<T>、IEnumerable<T>,而 ArrayList是 一个非泛型 列表。 List<T> 默认 构造 一个空列表 ,添加元素后 会构建 4个元素,如过超过了的话 容量会 ,扩展倒两倍。如果容量改变 ,内容就会重新分配到新的内存中。创建新的数组,通过Array.Copy(). 所以事先知道他的 容量的话,给定容量 ,效率会更高。
有 初始值设定 ,添加元素 ,插入元素,访问元素,删除元素,收索,排序,类型转换,只读集合。
KeyValuePair 首先 KeyValuePair 是单个键值对象,一般是配合Dictionary 或 SortedDictionary
12down voteaccepted
|
Hashtable is random access and internally uses System.Collections.DictionaryEntry for its items from .NET 1.1; whereas a strongly typed System.Collections.Generic.Dictionary in .NET 2.0 usesSystem.Collections.Generic.KeyValuePair items and is also random access. (Note: This answer is biased toward the .NET 2.0 framework when providing examples - that's why it continues with KeyValuePair instead of DictionaryEntry - the original question indicates this is the desired Type to work with.) Because KeyValuePair is an independent class, you can manually make a List or Array of KeyValuePair instances, but a list or array will be sequentially accessed. This is in contrast to the Hashtable or Dictionary which internally creates its own element instances and is randomly accessed. Both are valid ways of using KeyValuePair instances. Also see see MSDN info about selecting a Collection class to use. In summary: sequential access is fastest when using a small set of items whereas a larger set of items benefits from random access. Microsoft's hybrid solution: An interesting specialized collection introduced in .NET 1.1 isSystem.Collections.Specialized.HybridDictionary which uses a ListDictionary internal representation (sequentially accessed) while the collection is small, and then automatically switches to a Hashtable internal representation (randomly accessed) when the collection gets large". C# Sample Code The following samples show the same Key-Value pair instances created for different scenarios - sequential access (two examples) followed by one example of random access. For simplicity in these examples they will all use an int key with string value - you can substitute in the data types you need to use. Here's a strongly-typed System.Collections.Generic.List of key-value pairs.
Here's a System.Array of key-value pairs.
Here's a Dictionary of Key-Value pairs.
|
HashTable
队列:队列 先进先出,Queue<T> 实现了 ICollection 和 IEnumerable <T> 接口 没有实现 IConllection<T> 接口,add remove 方法不能用于队列。 也没有实现IList<T>接口,不能用索引器访问队列。内部用 T[] 实现。待续
栈 : 先进 后出的结构,在foreach 方法中 ,IEnumerable接口迭代所有元素,栈的枚举器不会删除元素。
链表: 带续
字典: 字典是个很复杂的数据结构,它能根据键,快速查找值。也可以自由添加 和 删除元素。 有点像List<T>,但没有内存中移动后续元素的性能 开销。
作为字典中键的类型必须重写Object类的 GetHashCode() 方法,因为字典要确定元素的位置,他要调用GetHashCode() 返回的int来计算在对应位置放置的元素索引。它涉及素数,字典的容量是一个素数。 字典的新能取决于GetHashCode()的代码。
键类型还需要重写IEquatable<T>.Equals()方法。或重写Object的Equals() 方法。 如果A.Equals(B)返回true ,则 A.GetHashCode() 和 B.GetHashCode(); 如果设计出的某种重写这些方法的方式不满足 这个条件,而把它作为键的话,就会出现索引不到值的现象。
Equals方法 比较的是引用,,GetHashCode()返回的是一个仅基于对象地址的散列代码。如果 散列表基于一个键 ,而建没有重写这些方法,这个散列表就能 正常工作。 但是这么做 只有 对象完全相同,键才被认为是相等的。
String实现了IEquatable 接口,并重载了 GetHashCode() 方法,Equals()提供了值的比较,GEtHashCode() 根据字符串的值返回一个散列表代码。 字典中用字符串作为 键值很方便。
int32并不适合在字典中使用。 这些类型的返回 散列代码 只映射 到值上。 如果希望用作键的数值 本身没有分布在 可能的整数范围内,把整数作为键值就不好了。