类型参数TKey 字典中的键的类型。TValue 字典中的值的类型。Dictionary<(Of <(TKey, TValue>)>) 泛型类提供了从一组键到一组值的映射。字典中的每个添加项都由一个值及其相关联的键组成。通过键来检索值的速度是非常快的,接近于 O(1),这是因为 Dictionary<(Of <(TKey, TValue>)>) 类是作为一个哈希表来实现的。注意: 检索速度取决于为 TKey 指定的类型的哈希算法的质量。只要对象用作 Dictionary<(Of <(TKey, TValue>)>) 中的键,它就不能以任何影响其哈希值的方式更改。使用字典的相等比较器比较时,Dictionary<(Of <(TKey, TValue>)>) 中的任何键都必须是唯一的。键不能为 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing),但是如果值类型 TValue 为引用类型,该值则可以为空。Dictionary<(Of <(TKey, TValue>)>) 需要一个相等实现来确定键是否相等。可以使用一个接受 comparer 参数的构造函数来指定 IEqualityComparer<(Of <(T>)>) 泛型接口的实现;如果不指定实现,则使用默认的泛型相等比较器 EqualityComparer<(Of <(T>)>)..::.Default。如果类型 TKey 实现 System..::.IEquatable<(Of <(T>)>) 泛型接口,则默认相等比较器会使用该实现。注意: 例如,您可以使用 StringComparer 类提供的不区分大小写的字符串比较器来创建带不区分大小写的字符串键的字典。Dictionary<(Of <(TKey, TValue>)>) 的容量是 Dictionary<(Of <(TKey, TValue>)>) 可以包含的元素数。当向 Dictionary<(Of <(TKey, TValue>)>) 中添加元素时,将通过重新分配内部数组来根据需要自动增大容量。对于枚举而言,字典中的每一项都被视为一个表示值及其键的 KeyValuePair<(Of <(TKey, TValue>)>) 结构进行处理。项返回的顺序未定义。C# 语言的 foreach 语句(在 C++ 中为 for each,在 Visual Basic 中为 For Each)需要集合中每个元素的类型。由于 Dictionary<(Of <(TKey, TValue>)>) 是键和值的集合,因此元素类型并非键类型或值类型。相反,元素类型是键类型和值类型的 KeyValuePair<(Of <(TKey, TValue>)>)。例如:foreach (KeyValuePair<int, string> kvp in myDictionary) {...}下面的代码示例创建一个空的带有字符串键的字符串 Dictionary<(Of <(TKey, TValue>)>),并使用 Add 方法添加一些元素。该示例演示在尝试添加重复的键时 Add 方法引发 ArgumentException。该示例使用 Item 属性(在 C# 中为 索引器)来检索值,演示当请求的键不存在时将引发 KeyNotFoundException,并演示与键相关联的值可被替换。该示例演示,如果程序必须经常尝试词典中不存在的键值,如何使用 TryGetValue 方法作为更有效的检索值的方法,该示例还演示在调用 Add 方法之前如何使用 ContainsKey 方法来测试键是否存在。该示例演示如何枚举字典中的键和值,以及如何分别使用 Keys 属性和 Values 属性来单独枚举键和值。最后,该示例演示 Remove 方法using System; using System.Collections.Generic;public class Example { public static void Main() { // Create a new dictionary of strings, with string keys. // Dictionary<string, string> openWith = new Dictionary<string, string>(); // Add some elements to the dictionary. There are no // duplicate keys, but some of the values are duplicates. openWith.Add("txt", "notepad.exe"); openWith.Add("bmp", "paint.exe"); openWith.Add("dib", "paint.exe"); openWith.Add("rtf", "wordpad.exe"); // The Add method throws an exception if the new key is // already in the dictionary. try { openWith.Add("txt", "winword.exe"); } catch (ArgumentException) { Console.WriteLine("An element with Key = \"txt\" already exists."); } // The Item property is another name for the indexer, so you // can omit its name when accessing elements. Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); // The indexer can be used to change the value associated // with a key. openWith["rtf"] = "winword.exe"; Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); // If a key does not exist, setting the indexer for that key // adds a new key/value pair. openWith["doc"] = "winword.exe"; // The indexer throws an exception if the requested key is // not in the dictionary. try { Console.WriteLine("For key = \"tif\", value = {0}.", openWith["tif"]); } catch (KeyNotFoundException) { Console.WriteLine("Key = \"tif\" is not found."); } // When a program often has to try keys that turn out not to // be in the dictionary, TryGetValue can be a more efficient // way to retrieve values. string value = ""; if (openWith.TryGetValue("tif", out value)) { Console.WriteLine("For key = \"tif\", value = {0}.", value); } else { Console.WriteLine("Key = \"tif\" is not found."); } // ContainsKey can be used to test keys before inserting // them. if (!openWith.ContainsKey("ht")) { openWith.Add("ht", "hypertrm.exe"); Console.WriteLine("Value added for key = \"ht\": {0}", openWith["ht"]); } // When you use foreach to enumerate dictionary elements, // the elements are retrieved as KeyValuePair objects. Console.WriteLine(); foreach( KeyValuePair<string, string> kvp in openWith ) { Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); } // To get the values alone, use the Values property. Dictionary<string, string>.ValueCollection valueColl = openWith.Values; // The elements of the ValueCollection are strongly typed // with the type that was specified for dictionary values. Console.WriteLine(); foreach( string s in valueColl ) { Console.WriteLine("Value = {0}", s); } // To get the keys alone, use the Keys property. Dictionary<string, string>.KeyCollection keyColl = openWith.Keys; // The elements of the KeyCollection are strongly typed // with the type that was specified for dictionary keys. Console.WriteLine(); foreach( string s in keyColl ) { Console.WriteLine("Key = {0}", s); } // Use the Remove method to remove a key/value pair. Console.WriteLine("\nRemove(\"doc\")"); openWith.Remove("doc"); if (!openWith.ContainsKey("doc")) { Console.WriteLine("Key \"doc\" is not found."); } } }/* This code example produces the following output:An element with Key = "txt" already exists. For key = "rtf", value = wordpad.exe. For key = "rtf", value = winword.exe. Key = "tif" is not found. Key = "tif" is not found. Value added for key = "ht": hypertrm.exeKey = txt, Value = notepad.exe Key = bmp, Value = paint.exe Key = dib, Value = paint.exe Key = rtf, Value = winword.exe Key = doc, Value = winword.exe Key = ht, Value = hypertrm.exeValue = notepad.exe Value = paint.exe Value = paint.exe Value = winword.exe Value = winword.exe Value = hypertrm.exeKey = txt Key = bmp Key = dib Key = rtf Key = doc Key = htRemove("doc") Key "doc" is not found. */此类型的公共静态(在 Visual Basic 中为 Shared)成员是线程安全的。但不能保证任何实例成员是线程安全的。只要不修改该集合,Dictionary<(Of <(TKey, TValue>)>) 就可以同时支持多个阅读器。 即便如此,从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。当出现枚举与写访问互相争用这种极少发生的情况时,必须在整个枚举过程中锁定集合。若要允许多个线程访问集合以进行读写操作,则必须实现自己的同步。
using System; using System.Collections;namespace program { class wangjun { /// <summary> /// 对哈希表进行遍历,使用了两种 方法(foreach dictionaryentry和 foreach string) /// </summary> /// <param name="args"></param> static void Main(string[] args) { //建立哈希表对象 Hashtable hs = new Hashtable();
hs.Add("13", "1234123"); hs.Add("2", "sadfgasd"); hs.Add("4", "23123fs"); hs.Add("3", "12312sdf"); hs.Add("5", "sdfgasdfg"); //删除元素 hs.Remove("13"); //使用字典方法遍历哈希表 foreach (DictionaryEntry dic in hs) { Console.WriteLine("key={0} value={1}",(string)dic.Key,(string)dic.Value); } //空白两行 for (int i = 0; i < 2; i++) { Console.WriteLine(); } //建立arraylist对象并得到了哈希表的键的集合实例,用于对哈希表的的排序+遍历 ArrayList al = new ArrayList(hs.Keys); //对arraylist中的值(哈希表键)进行名称排序 al.Sort(); //使用foreach进行遍历 foreach (string s in al) { //这里用到了(string)hs[s]因为哈希表存放的是object所以这里要进行强制转换 Console.WriteLine("key={0} value={1}",s,(string)hs[s]); } //空白两行 for (int i = 0; i < 2; i++) { Console.WriteLine(); } //对arraylist的值(哈希表的键)进行反向排序 al.Reverse(); foreach (string s in al) { //这里用到了(string)hs[s]因为哈希表存放的是object所以这里要进行强制转换 Console.WriteLine("key={0} value={1}",s,(string)hs[s]); } } } }
关于泛型,msdn里已解释得很清楚至于动态加载树形,给个讨论方向
(三)Stack:栈,表示对象的简单的后进先出非泛型集合。Push方法入栈,Pop方法出栈。 using System; using System.Collections.Generic; using System.Text; using System.Collections; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Stack sk = new Stack(); Stack sk2 = new Stack(); foreach (int i in new int[4] { 1, 2, 3, 4 }) { sk.Push(i);//入栈 sk2.Push(i); } foreach (int i in sk) { Console.WriteLine(i);//遍历 } sk.Pop();//出栈 Console.WriteLine("Pop"); foreach (int i in sk) { Console.WriteLine(i); } sk2.Peek();//弹出最后一项不删除 Console.WriteLine("Peek"); foreach (int i in sk2) { Console.WriteLine(i); } } } } (四)哈希表 一、哈希表(Hashtable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中key/value键值对均为object类型,所以Hashtable可以支持任何类型的key/value键值对. 二、哈希表的简单操作 在哈希表中添加一个key/value键值对:HashtableObject.Add(key,value); 在哈希表中去除某个key/value键值对:HashtableObject.Remove(key); 从哈希表中移除所有元素: HashtableObject.Clear(); 判断哈希表是否包含特定键key: HashtableObject.Contains(key); 下面控制台程序将包含以上所有操作: using System; using System.Collections; //使用Hashtable时,必须引入这个命名空间 class hashtable { public static void Main() { Hashtable ht=new Hashtable(); //创建一个Hashtable实例 ht.Add("E","e");//添加key/value键值对 ht.Add("A","a"); ht.Add("C","c"); ht.Add("B","b"); string s=(string)ht["A"]; if(ht.Contains("E")) //判断哈希表是否包含特定键,其返回值为true或false Console.WriteLine("the E key:exist"); ht.Remove("C");//移除一个key/value键值对 Console.WriteLine(ht["A"]);//此处输出a ht.Clear();//移除所有元素 Console.WriteLine(ht["A"]); //此处将不会有任何输出 } } 三、遍历哈希表 遍历哈希表需要用到DictionaryEntry Object,代码如下: for(DictionaryEntry de in ht) //ht为一个Hashtable实例 { Console.WriteLine(de.Key);//de.Key对应于key/value键值对key Console.WriteLine(de.Value);//de.Key对应于key/value键值对value } 四、对哈希表进行排序 对哈希表进行排序在这里的定义是对key/value键值对中的key按一定规则重新排列,但是实际上这个定义是不能实现的,因为我们无法直接在Hashtable进行对key进行重新排列,如果需要Hashtable提供某种规则的输出,可以采用一种变通的做法: ArrayList akeys=new ArrayList(ht.Keys); //别忘了导入System.Collections akeys.Sort(); //按字母顺序进行排序 foreach(string skey in akeys) { Console.Write(skey + ":"); Console.WriteLine(ht[skey]);//排序后输出 } (五)SortedList类:表示键/值对的集合,与哈希表类似,区别在于SortedList中的Key数组排好序的。 using System; using System.Collections.Generic; using System.Text; using System.Collections; namespace ConsoleApplication1 { class Program { public static void Main() { SortedList sl = new SortedList(); sl["c"] = 41; sl["a"] = 42; sl["d"] = 11; sl["b"] = 13; foreach (DictionaryEntry element in sl) { string s = (string)element.Key; int i = (int)element.Value; Console.WriteLine("{0},{1}", s, i); } } } } (六)Dictionary 泛型集合 泛型最常见的用途是泛型集合,命名空间System.Collections.Generic 中包含了一些基于泛型的集合类,使用泛型集合类可以提供更高的类型安全性,还有更高的性能,避免了非泛型集合的重复的装箱和拆箱。 很多非泛型集合类都有对应的泛型集合类,下面是常用的非泛型集合类以及对应的泛型集合类: 非泛型集合类 泛型集合类 ArrayList List<T> HashTable DIctionary<T> Queue Queue<T> Stack Stack<T> SortedList SortedList<T> 我们用的比较多的非泛型集合类主要有 ArrayList类 和 HashTable类。我们经常用HashTable 来存储将要写入到数据库或者返回的信息,在这之间要不断的进行类型的转化,增加了系统装箱和拆箱的负担,如果我们操纵的数据类型相对确定的化 用 Dictionary<TKey,TValue> 集合类来存储数据就方便多了,例如我们需要在电子商务网站中存储用户的购物车信息( 商品名,对应的商品个数)时,完全可以用 Dictionary<string, int> 来存储购物车信息,而不需要任何的类型转化。 下面是简单的例子,包括声明,填充键值对,移除键值对,遍历键值对 Dictionary<string, string> myDic = new Dictionary<string, string>(); myDic.Add("aaa", "111"); myDic.Add("bbb", "222"); myDic.Add("ccc", "333"); myDic.Add("ddd", "444"); //如果添加已经存在的键,add方法会抛出异常 try { myDic.Add("ddd","ddd"); } catch (ArgumentException ex) { Console.WriteLine("此键已经存在:" + ex.Message); } //解决add()异常的方法是用ContainsKey()方法来判断键是否存在 if (!myDic.ContainsKey("ddd")) { myDic.Add("ddd", "ddd"); } else { Console.WriteLine("此键已经存在:");
但是我还是要顶!
使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
泛型最常见的用途是创建集合类。
.NET Framework 类库在 System.Collections.Generic 命名空间中包含几个新的泛型集合类。应尽可能地使用这些类来代替普通的类,如 System.Collections 命名空间中的 ArrayList,HashTable等。
下面我们就来说下,几个泛型集合类的用法:一.Dictionary
此类在 .NET Framework 2.0 版中是新增的。表示键和值的集合。命名空间:System.Collections.Generic,程序集:mscorlib(在 mscorlib.dll 中)
class TestGenericList
{
static void Main()
{
//声明对象,参数表示,键是int类型,值是string类型
Dictionary<int, string> fruit = new Dictionary<int, string>();
try{
//加入重复键会引发异常
fruit.Add(1, "苹果");
fruit.Add(2, "桔子");
fruit.Add(3, "香蕉");
fruit.Add(4, "菠萝");
//参数错误将引发异常,如下所示
//fruit.Add("5", "aa");
}
catch (ArgumentException)
{
Console.WriteLine("添加错误!!!");
}
//因为引入了泛型,所以键取出后不需要进行Object到int的转换,值的集合也一样
foreach (int i in fruit.Keys)
{
Console.WriteLine("键是:{0} 值是:{1}",i,fruit);
}
//删除指定键,值
fruit.Remove(1);
//判断是否包含指定键
if (fruit.ContainsKey(1))
{
Console.WriteLine("包含此键");
}
//清除集合中所有对象
fruit.Clear();
}
}
Dictionary遍历输出的顺序,就是加入的顺序,这点与Hashtable不同,其它方法如:ContainsKey ,ContainsValue ,Remove 等,使用方法基本一致。二、List类
注意:此类在 .NET Framework 2.0 版中是新增的。表示可通过索引访问的对象的强类型列表。提供用于对列表进行搜索、排序和操作的方法。命名空间:System.Collections.Generic,程序集:mscorlib(在 mscorlib.dll 中),List 类是 ArrayList 类的泛型等效类。 //声明一个泛型类
class TestGenericList
{
static void Main()
{
//声明一个List对象,只加入string参数
List<string> names = new List<string>();
names.Add("乔峰");
names.Add("欧阳峰");
names.Add("马蜂");
//遍历List
foreach (string name in names)
{
Console.WriteLine(name);
}
//向List中插入元素
names.Insert(2, "张三峰");
//移除指定元素
names.Remove("马蜂");
}
}
在决定使用 List 还是使用 ArrayList 类(两者具有类似的功能)时,记住 List 类在大多数情况下执行得更好并且是类型安全的。如果对 List 类的类型 T 使用引用类型,则两个类的行为是完全相同的。但是,如果对类型 T 使用值类型,则需要考虑实现和装箱问题。如果对类型 T 使用值类型,则编译器将特别针对该值类型生成 List 类的实现。这意味着不必对 List 对象的列表元素进行装箱就可以使用该元素,并且在创建大约 500 个列表元素之后,不对列表元素装箱所节省的内存将大于生成该类实现所使用的内存。其实我们也可以自己定义一个泛型类,如下所示:
//声明一个泛型类
public class ItemList<T>
{
void Add(T item) { }
}
class TestGenericList
{
private class ExampleClass { }
static void Main()
{
// 声明一个对象,只能加入int型
ItemList<int> list1 = new ItemList<int>(); //声明一个对象,只能加入Student类型,Student类为自定义类
ItemList<Student> list2 = new ItemList<Student>(); }
}泛型的用法还有很多种,如泛型方法,泛型委托,泛型接口等。
//定义数据字典
Dictionary<ClassA, List<ClassB>> dictionaryDemo= new Dictionary<ClassA, List<ClassB>>();//主表类存在一个对象 objClassA和一个对象列表 List<ClassA> listClassA,子表类存在一个对象列表 List<ClassB> listClassB//数据字典赋值
dictionaryDemo[objClassA] = listClassB;
//为子列表指定值
listClassB = dictionaryDemo[objClassA];//主表列表赋值
listClassA = new List<ClassA>(dictionaryDemo.Keys);
Hashtable, ArrayList, List, Dictionary
Hashtable用法在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中key/value键值对均为object类型,所以Hashtable可以支持任何类型的key/value键值对.。在哈希表中添加一个key/value键值对:HashtableObject.Add(key,value);
在哈希表中去除某个key/value键值对:HashtableObject.Remove(key);
从哈希表中移除所有元素: HashtableObject.Clear();
判断哈希表是否包含特定键key: HashtableObject.Contains(key); Hashtable ht = new Hashtable(); ht.Add("a", 123); ht.Add("b", 456);
// 遍历哈希表需要用到DictionaryEntry Object foreach (DictionaryEntry de in ht) { MessageBox.Show(de.Key.ToString() + " " + de.Value.ToString()); } //对哈希表进行排序 ArrayList akeys = new ArrayList(ht.Keys); //别忘了导入System.Collections akeys.Sort(); //按字母顺序进行排序 foreach (string skey in akeys) { MessageBox.Show(skey + ":"); MessageBox.Show(ht[skey].ToString());//排序后输出 }ArrayList用法private static void AddToList(ArrayList list, string p) { if (list.Contains(p) == false) list.Add(p); } private void button1_Click(object sender, EventArgs e) { ArrayList list = new ArrayList(); AddToList(list, "Table1"); AddToList(list, "Table4"); AddToList(list, "Table1"); AddToList(list, "Table3"); AddToList(list, "Table2"); AddToList(list, "Table2"); foreach (string s in list) { MessageBox.Show(s); } }ListList<string> listStr = new List<string>(); listStr.Add("123"); listStr.Add("456"); listStr.Add("789"); MessageBox.Show(listStr[2]);//”789” Dictionary泛型的优点(C# 编程指南)C# 中典型的范型结构除了熟悉的 IList , HashTable之外还有一个并不常见的Dictionary集合。相比较而言,Dictionary的性能是最好的,也属于轻便型的集合。效率要大于HashTable,其主要原因是Dictionary支持强类型声明的。在公共语言运行库和 C# 语言的早期版本中,通用化是通过在类型与通用基类型 Object 之间进行强制转换来实现的,泛型提供了针对这种限制的解决方案。通过创建泛型类,您可以创建一个在编译时类型安全的集合。添加到 ArrayList 中的任何引用或值类型都将隐式地向上强制转换为 Object。如果项是值类型,则必须在将其添加到列表中时进行装箱操作,在检索时进行取消装箱操作。强制转换以及装箱和取消装箱操作都会降低性能;在必须对大型集合进行循环访问的情况下,装箱和取消装箱的影响非常明显。对于客户端代码,与 ArrayList 相比,使用 List<T> 时添加的唯一语法是声明和实例化中的类型参数。虽然这稍微增加了些编码的复杂性,但好处是您可以创建一个比 ArrayList 更安全并且速度更快的列表,特别适用于列表项是值类型的情况。Dictionary 泛型类提供了从一组键到一组值的映射。字典中的每个添加项都由一个值及其相关联的键组成。通过键来检索值的速度是非常快的,接近于 O(1),这是因为 Dictionary 类是作为一个哈希表来实现的。1、Dictionary<int, string> fruit = new Dictionary<int, string>(); //加入重复键会引发异常 fruit.Add(1, "苹果"); fruit.Add(2, "桔子"); fruit.Add(3, "香蕉"); fruit.Add(4, "菠萝"); //因为引入了泛型,所以键取出后不需要进行Object到int的转换,值的集合也一样 foreach (int i in fruit.Keys) { MessageBox.Show("键是:"+i.ToString()+ "值是:"+ fruit[i]); }
类型参数TKey
字典中的键的类型。TValue
字典中的值的类型。Dictionary<(Of <(TKey, TValue>)>) 泛型类提供了从一组键到一组值的映射。字典中的每个添加项都由一个值及其相关联的键组成。通过键来检索值的速度是非常快的,接近于 O(1),这是因为 Dictionary<(Of <(TKey, TValue>)>) 类是作为一个哈希表来实现的。注意:
检索速度取决于为 TKey 指定的类型的哈希算法的质量。只要对象用作 Dictionary<(Of <(TKey, TValue>)>) 中的键,它就不能以任何影响其哈希值的方式更改。使用字典的相等比较器比较时,Dictionary<(Of <(TKey, TValue>)>) 中的任何键都必须是唯一的。键不能为 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing),但是如果值类型 TValue 为引用类型,该值则可以为空。Dictionary<(Of <(TKey, TValue>)>) 需要一个相等实现来确定键是否相等。可以使用一个接受 comparer 参数的构造函数来指定 IEqualityComparer<(Of <(T>)>) 泛型接口的实现;如果不指定实现,则使用默认的泛型相等比较器 EqualityComparer<(Of <(T>)>)..::.Default。如果类型 TKey 实现 System..::.IEquatable<(Of <(T>)>) 泛型接口,则默认相等比较器会使用该实现。注意:
例如,您可以使用 StringComparer 类提供的不区分大小写的字符串比较器来创建带不区分大小写的字符串键的字典。Dictionary<(Of <(TKey, TValue>)>) 的容量是 Dictionary<(Of <(TKey, TValue>)>) 可以包含的元素数。当向 Dictionary<(Of <(TKey, TValue>)>) 中添加元素时,将通过重新分配内部数组来根据需要自动增大容量。对于枚举而言,字典中的每一项都被视为一个表示值及其键的 KeyValuePair<(Of <(TKey, TValue>)>) 结构进行处理。项返回的顺序未定义。C# 语言的 foreach 语句(在 C++ 中为 for each,在 Visual Basic 中为 For Each)需要集合中每个元素的类型。由于 Dictionary<(Of <(TKey, TValue>)>) 是键和值的集合,因此元素类型并非键类型或值类型。相反,元素类型是键类型和值类型的 KeyValuePair<(Of <(TKey, TValue>)>)。例如:foreach (KeyValuePair<int, string> kvp in myDictionary) {...}下面的代码示例创建一个空的带有字符串键的字符串 Dictionary<(Of <(TKey, TValue>)>),并使用 Add 方法添加一些元素。该示例演示在尝试添加重复的键时 Add 方法引发 ArgumentException。该示例使用 Item 属性(在 C# 中为 索引器)来检索值,演示当请求的键不存在时将引发 KeyNotFoundException,并演示与键相关联的值可被替换。该示例演示,如果程序必须经常尝试词典中不存在的键值,如何使用 TryGetValue 方法作为更有效的检索值的方法,该示例还演示在调用 Add 方法之前如何使用 ContainsKey 方法来测试键是否存在。该示例演示如何枚举字典中的键和值,以及如何分别使用 Keys 属性和 Values 属性来单独枚举键和值。最后,该示例演示 Remove 方法using System;
using System.Collections.Generic;public class Example
{
public static void Main()
{
// Create a new dictionary of strings, with string keys.
//
Dictionary<string, string> openWith =
new Dictionary<string, string>(); // Add some elements to the dictionary. There are no
// duplicate keys, but some of the values are duplicates.
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe"); // The Add method throws an exception if the new key is
// already in the dictionary.
try
{
openWith.Add("txt", "winword.exe");
}
catch (ArgumentException)
{
Console.WriteLine("An element with Key = \"txt\" already exists.");
} // The Item property is another name for the indexer, so you
// can omit its name when accessing elements.
Console.WriteLine("For key = \"rtf\", value = {0}.",
openWith["rtf"]); // The indexer can be used to change the value associated
// with a key.
openWith["rtf"] = "winword.exe";
Console.WriteLine("For key = \"rtf\", value = {0}.",
openWith["rtf"]); // If a key does not exist, setting the indexer for that key
// adds a new key/value pair.
openWith["doc"] = "winword.exe"; // The indexer throws an exception if the requested key is
// not in the dictionary.
try
{
Console.WriteLine("For key = \"tif\", value = {0}.",
openWith["tif"]);
}
catch (KeyNotFoundException)
{
Console.WriteLine("Key = \"tif\" is not found.");
} // When a program often has to try keys that turn out not to
// be in the dictionary, TryGetValue can be a more efficient
// way to retrieve values.
string value = "";
if (openWith.TryGetValue("tif", out value))
{
Console.WriteLine("For key = \"tif\", value = {0}.", value);
}
else
{
Console.WriteLine("Key = \"tif\" is not found.");
} // ContainsKey can be used to test keys before inserting
// them.
if (!openWith.ContainsKey("ht"))
{
openWith.Add("ht", "hypertrm.exe");
Console.WriteLine("Value added for key = \"ht\": {0}",
openWith["ht"]);
} // When you use foreach to enumerate dictionary elements,
// the elements are retrieved as KeyValuePair objects.
Console.WriteLine();
foreach( KeyValuePair<string, string> kvp in openWith )
{
Console.WriteLine("Key = {0}, Value = {1}",
kvp.Key, kvp.Value);
} // To get the values alone, use the Values property.
Dictionary<string, string>.ValueCollection valueColl =
openWith.Values; // The elements of the ValueCollection are strongly typed
// with the type that was specified for dictionary values.
Console.WriteLine();
foreach( string s in valueColl )
{
Console.WriteLine("Value = {0}", s);
} // To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl =
openWith.Keys; // The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
Console.WriteLine("Key = {0}", s);
} // Use the Remove method to remove a key/value pair.
Console.WriteLine("\nRemove(\"doc\")");
openWith.Remove("doc"); if (!openWith.ContainsKey("doc"))
{
Console.WriteLine("Key \"doc\" is not found.");
}
}
}/* This code example produces the following output:An element with Key = "txt" already exists.
For key = "rtf", value = wordpad.exe.
For key = "rtf", value = winword.exe.
Key = "tif" is not found.
Key = "tif" is not found.
Value added for key = "ht": hypertrm.exeKey = txt, Value = notepad.exe
Key = bmp, Value = paint.exe
Key = dib, Value = paint.exe
Key = rtf, Value = winword.exe
Key = doc, Value = winword.exe
Key = ht, Value = hypertrm.exeValue = notepad.exe
Value = paint.exe
Value = paint.exe
Value = winword.exe
Value = winword.exe
Value = hypertrm.exeKey = txt
Key = bmp
Key = dib
Key = rtf
Key = doc
Key = htRemove("doc")
Key "doc" is not found.
*/此类型的公共静态(在 Visual Basic 中为 Shared)成员是线程安全的。但不能保证任何实例成员是线程安全的。只要不修改该集合,Dictionary<(Of <(TKey, TValue>)>) 就可以同时支持多个阅读器。 即便如此,从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。当出现枚举与写访问互相争用这种极少发生的情况时,必须在整个枚举过程中锁定集合。若要允许多个线程访问集合以进行读写操作,则必须实现自己的同步。
using System.Collections;namespace program
{
class wangjun
{
/// <summary>
/// 对哈希表进行遍历,使用了两种 方法(foreach dictionaryentry和 foreach string)
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
//建立哈希表对象
Hashtable hs = new Hashtable();
hs.Add("13", "1234123");
hs.Add("2", "sadfgasd");
hs.Add("4", "23123fs");
hs.Add("3", "12312sdf");
hs.Add("5", "sdfgasdfg");
//删除元素
hs.Remove("13");
//使用字典方法遍历哈希表
foreach (DictionaryEntry dic in hs)
{
Console.WriteLine("key={0} value={1}",(string)dic.Key,(string)dic.Value);
}
//空白两行
for (int i = 0; i < 2; i++)
{
Console.WriteLine();
}
//建立arraylist对象并得到了哈希表的键的集合实例,用于对哈希表的的排序+遍历
ArrayList al = new ArrayList(hs.Keys);
//对arraylist中的值(哈希表键)进行名称排序
al.Sort();
//使用foreach进行遍历
foreach (string s in al)
{
//这里用到了(string)hs[s]因为哈希表存放的是object所以这里要进行强制转换
Console.WriteLine("key={0} value={1}",s,(string)hs[s]);
}
//空白两行
for (int i = 0; i < 2; i++)
{
Console.WriteLine();
}
//对arraylist的值(哈希表的键)进行反向排序
al.Reverse();
foreach (string s in al)
{
//这里用到了(string)hs[s]因为哈希表存放的是object所以这里要进行强制转换
Console.WriteLine("key={0} value={1}",s,(string)hs[s]);
}
}
}
}
(三)Stack:栈,表示对象的简单的后进先出非泛型集合。Push方法入栈,Pop方法出栈。
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Stack sk = new Stack();
Stack sk2 = new Stack();
foreach (int i in new int[4] { 1, 2, 3, 4 })
{
sk.Push(i);//入栈
sk2.Push(i);
}
foreach (int i in sk)
{
Console.WriteLine(i);//遍历
}
sk.Pop();//出栈
Console.WriteLine("Pop");
foreach (int i in sk)
{
Console.WriteLine(i);
}
sk2.Peek();//弹出最后一项不删除
Console.WriteLine("Peek");
foreach (int i in sk2)
{
Console.WriteLine(i);
}
}
}
}
(四)哈希表
一、哈希表(Hashtable)简述
在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中key/value键值对均为object类型,所以Hashtable可以支持任何类型的key/value键值对.
二、哈希表的简单操作
在哈希表中添加一个key/value键值对:HashtableObject.Add(key,value);
在哈希表中去除某个key/value键值对:HashtableObject.Remove(key);
从哈希表中移除所有元素: HashtableObject.Clear();
判断哈希表是否包含特定键key: HashtableObject.Contains(key);
下面控制台程序将包含以上所有操作:
using System;
using System.Collections; //使用Hashtable时,必须引入这个命名空间
class hashtable
{
public static void Main()
{
Hashtable ht=new Hashtable(); //创建一个Hashtable实例
ht.Add("E","e");//添加key/value键值对
ht.Add("A","a");
ht.Add("C","c");
ht.Add("B","b");
string s=(string)ht["A"];
if(ht.Contains("E")) //判断哈希表是否包含特定键,其返回值为true或false
Console.WriteLine("the E key:exist");
ht.Remove("C");//移除一个key/value键值对
Console.WriteLine(ht["A"]);//此处输出a
ht.Clear();//移除所有元素
Console.WriteLine(ht["A"]); //此处将不会有任何输出
}
}
三、遍历哈希表
遍历哈希表需要用到DictionaryEntry Object,代码如下:
for(DictionaryEntry de in ht) //ht为一个Hashtable实例
{
Console.WriteLine(de.Key);//de.Key对应于key/value键值对key
Console.WriteLine(de.Value);//de.Key对应于key/value键值对value
}
四、对哈希表进行排序
对哈希表进行排序在这里的定义是对key/value键值对中的key按一定规则重新排列,但是实际上这个定义是不能实现的,因为我们无法直接在Hashtable进行对key进行重新排列,如果需要Hashtable提供某种规则的输出,可以采用一种变通的做法:
ArrayList akeys=new ArrayList(ht.Keys); //别忘了导入System.Collections
akeys.Sort(); //按字母顺序进行排序
foreach(string skey in akeys)
{
Console.Write(skey + ":");
Console.WriteLine(ht[skey]);//排序后输出
}
(五)SortedList类:表示键/值对的集合,与哈希表类似,区别在于SortedList中的Key数组排好序的。
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
public static void Main()
{
SortedList sl = new SortedList();
sl["c"] = 41;
sl["a"] = 42;
sl["d"] = 11;
sl["b"] = 13;
foreach (DictionaryEntry element in sl)
{
string s = (string)element.Key;
int i = (int)element.Value;
Console.WriteLine("{0},{1}", s, i);
}
}
}
}
(六)Dictionary 泛型集合
泛型最常见的用途是泛型集合,命名空间System.Collections.Generic 中包含了一些基于泛型的集合类,使用泛型集合类可以提供更高的类型安全性,还有更高的性能,避免了非泛型集合的重复的装箱和拆箱。
很多非泛型集合类都有对应的泛型集合类,下面是常用的非泛型集合类以及对应的泛型集合类:
非泛型集合类 泛型集合类
ArrayList List<T>
HashTable DIctionary<T>
Queue Queue<T>
Stack Stack<T>
SortedList SortedList<T>
我们用的比较多的非泛型集合类主要有 ArrayList类 和 HashTable类。我们经常用HashTable 来存储将要写入到数据库或者返回的信息,在这之间要不断的进行类型的转化,增加了系统装箱和拆箱的负担,如果我们操纵的数据类型相对确定的化 用 Dictionary<TKey,TValue> 集合类来存储数据就方便多了,例如我们需要在电子商务网站中存储用户的购物车信息( 商品名,对应的商品个数)时,完全可以用 Dictionary<string, int> 来存储购物车信息,而不需要任何的类型转化。
下面是简单的例子,包括声明,填充键值对,移除键值对,遍历键值对
Dictionary<string, string> myDic = new Dictionary<string, string>();
myDic.Add("aaa", "111");
myDic.Add("bbb", "222");
myDic.Add("ccc", "333");
myDic.Add("ddd", "444");
//如果添加已经存在的键,add方法会抛出异常
try
{
myDic.Add("ddd","ddd");
}
catch (ArgumentException ex)
{
Console.WriteLine("此键已经存在:" + ex.Message);
}
//解决add()异常的方法是用ContainsKey()方法来判断键是否存在
if (!myDic.ContainsKey("ddd"))
{
myDic.Add("ddd", "ddd");
}
else
{
Console.WriteLine("此键已经存在:");
}
//而使用索引器来负值时,如果建已经存在,就会修改已有的键的键值,而不会抛出异常
myDic ["ddd"]="ddd";
myDic["eee"] = "555";
//使用索引器来取值时,如果键不存在就会引发异常
try
{
Console.WriteLine("不存在的键\"fff\"的键值为:" + myDic["fff"]);
}
catch (KeyNotFoundException ex)
{
Console.WriteLine("没有找到键引发异常:" + ex.Message);
}
//解决上面的异常的方法是使用ContarnsKey() 来判断时候存在键,如果经常要取健值得化最好用 TryGetValue方法来获取集合中的对应键值
string value = "";
if (myDic.TryGetValue("fff", out value))
{
Console.WriteLine("不存在的键\"fff\"的键值为:" + value );
}
else
{
Console.WriteLine("没有找到对应键的键值");
}
//下面用foreach 来遍历键值对
//泛型结构体 用来存储健值对
foreach (KeyValuePair<string, string> kvp in myDic)
{
Console.WriteLine("key={0},value={1}", kvp.Key, kvp.Value);
}
//获取值得集合
foreach (string s in myDic.Values)
{
Console.WriteLine("value={0}", s);
}
//获取值得另一种方式
Dictionary<string, string>.ValueCollection values = myDic.Values;
foreach (string s in values)
{
Console.WriteLine("value={0}", s);
}
常用的属性和方法如下:
常用属性 属性说明
Comparer 获取用于确定字典中的键是否相等的 IEqualityComparer。
Count 获取包含在 Dictionary 中的键/值对的数目。
Item 获取或设置与指定的键相关联的值。
Keys 获取包含 Dictionary 中的键的集合。
Values 获取包含 Dictionary 中的值的集合。
常用的方法 方法说明
Add 将指定的键和值添加到字典中。
Clear 从 Dictionary 中移除所有的键和值。
ContainsKey 确定 Dictionary 是否包含指定的键。
ContainsValue 确定 Dictionary 是否包含特定值。
Equals 已重载。 确定两个 Object 实例是否相等。 (从 Object 继承。)
GetEnumerator 返回循环访问 Dictionary 的枚举数。
GetHashCode 用作特定类型的哈希函数。GetHashCode 适合在哈希算法和数据结构(如哈希表)中使用。 (从 Object 继承。)
GetObjectData 实现 System.Runtime.Serialization.ISerializable 接口,并返回序列化 Dictionary 实例所需的数据。
GetType 获取当前实例的 Type。 (从 Object 继承。)
OnDeserialization 实现 System.Runtime.Serialization.ISerializable 接口,并在完成反序列化之后引发反序列化事件。
ReferenceEquals 确定指定的 Object 实例是否是相同的实例。 (从 Object 继承。)
Remove 从 Dictionary 中移除所指定的键的值。
ToString 返回表示当前 Object 的 String。 (从 Object 继承。)
TryGetValue 获取与指定的键相关联的值。
http://www.cnblogs.com/lsxqw2004/archive/2009/01/29/1381339.html
dict.Add("1", "test");
.
.
.
foreach (KeyValuePair<string, string> col in dict)
{
string strKey = col.Key;
string strValue = col.Value;}
//Dictionary<Tkey,TValue>是泛型字典,里面的key值不能为空、不能修改、值必须唯一,Tvalue就和使用泛型一样的了,如:
Dictionary<int, String> test = new Dictionary<int, string>();
for (int i = 0; i < 10;i++ )
{
test.Add(i, "Test" + i.ToString());
}
(test.OrderBy(u => u.Key)).ToList().ForEach(delegate(KeyValuePair<int, String> obj) { MessageBox.Show("TKey:"+obj.Key.ToString() + "\nTValue:" + obj.Value); });
public void BuildConstItems(string selectIndex)
{
///应该写出递归程序但是还是没有写出来,郁闷!
string strSele="";
DataSet ds;
DataTable dt;
FillTree ft=new FillTree();
ds=ft.GetLayer();
dt=ds.Tables[0];
TreeView1.Nodes.Clear();
for(int i=0;i<dt.Rows.Count;i++)
{
//father
TreeNode subnode1= new TreeNode();
subnode1.Text=dt.Rows[i][1].ToString();
subnode1.ID=dt.Rows[i][0].ToString();
subnode1.ImageUrl=Request.ApplicationPath+"/img/folder.gif";
subnode1.ExpandedImageUrl=Request.ApplicationPath+"/img/folderopen.gif";
subnode1.NavigateUrl="yoururl";
subnode1.Target="right" ;
//创建子目录
//son
}
dts=null;
TreeView1.Nodes.Add(subnode1);
}
// TreeView1.ExpandLevel=2;
// TreeView1.SelectedNodeIndex=selectIndex;
ds=null;
ft=null;
}
权限在数据库里设置
如:表TreeMenu
NodeId,ParentId,Text,Url
protected void Page_Load(object sender, EventArgs e)
{
BindCategoryTreeVew(CategoryView, true, "0");
}
public DataSet GetCategorys()
{
string ConnectionString = ConfigurationManager.AppSettings["ConnectionString"];
string sql = "select * from TreeMenu ";
SqlDataAdapter sda = new SqlDataAdapter(sql, ConnectionString);
DataSet ds = new DataSet();
sda.Fill(ds);
return ds;
}
public void BindCategoryTreeVew(TreeView treeView, bool isExpanded, string sSelectedData)
{
//将获取的数据转换为 一个DataTable
DataTable dt = GetCategorys().Tables[0];
treeView.Nodes.Clear();//清空 树的所有节点
//获取与排序顺序中的筛选器以及指定的状态相匹配的所有System.Data.DataRow 数组
DataRow[] rowlist = dt.Select("ParentId='0'");
if (rowlist.Length <= 0) return;
//创建跟节点
TreeNode rootNode = new TreeNode();
//设置根节点的属性
rootNode.Text = rowlist[0]["Text"].ToString();
//设置根节点的值
rootNode.Value = rowlist[0]["NodeId"].ToString();
rootNode.Expanded = isExpanded;
rootNode.Selected = true;
//添加跟节点
CategoryView.Nodes.Add(rootNode);
CreateChildNode(rootNode, dt, isExpanded, sSelectedData); }
private void CreateChildNode(TreeNode parentNode, DataTable dt, bool isExpanded, string sSelecedData)
{
//选择数据,添加排序表达市
DataRow[] rowList = dt.Select("ParentId=" + Convert.ToInt32(parentNode.Value));
foreach (DataRow row in rowList)
{
//创建一个新的节点了
TreeNode node = new TreeNode();
node.Text = row["Text"].ToString();
node.Value = row["NodeId"].ToString();
node.NavigateUrl=row["Url"].ToString();
node.Expanded = isExpanded;
if (node.Value == sSelecedData)
{
node.Selected = true;
}
parentNode.ChildNodes.Add(node);
//递归调用,创建其他节点
CreateChildNode(node, dt, isExpanded, sSelecedData);
}
}
Dictionnary<>是O(1)这个最关键。
Dictionary 是对应于 Hashtable 的泛型类。
Collection 是对应于 CollectionBase 的泛型类。
Collection 可以用作基类,但是与 CollectionBase 不同的是它不是抽象的,因而更易于使用。
ReadOnlyCollection 是对应于 ReadOnlyCollectionBase 的泛型类。
ReadOnlyCollection 不是抽象的,它具有一个构造函数,该构造函数使其更易于将现有的 List 公开为只读集合。
Queue、Stack 和 SortedList 泛型类分别对应于与其同名的非泛型类。Hashtable是键值对的集合,可以为OBJECT类型,不管用上面的那种,是要根据自己的业务操作而定,方法大志上差不多的。
用的比较多的是List<T> 和 HashTable