C#编程:深入理解HashTable的序列化与操作

需积分: 31 17 下载量 174 浏览量 更新于2024-09-23 收藏 48KB DOC 举报
“本文详细介绍了C#中如何使用HashTable进行序列化的具体方法,包括哈希表的基本操作、遍历哈希表以及序列化的实现。” 在C#编程语言中,序列化是一个关键概念,它允许我们将对象的状态转换为可以存储或传输的数据格式,如XML、JSON或二进制。而当涉及到像HashTable这样的数据结构时,序列化就显得尤为重要,因为这可以让我们保存和恢复数据结构的状态,以便在不同的时间点或不同的应用程序之间使用。 HashTable是.NET Framework中的一个容器,用于存储键值对(key-value pairs)。每个键必须是唯一的,它用于快速查找对应的值。以下是一些关于在C#中操作HashTable的基本操作: 1. 创建与初始化: 创建一个新的HashTable实例,例如: ```csharp Hashtable ht = new Hashtable(); ``` 2. 添加键值对: 使用`Add()`方法添加键值对到哈希表中: ```csharp ht.Add("key", "value"); ``` 3. 移除键值对: 使用`Remove()`方法移除指定键的键值对: ```csharp ht.Remove("key"); ``` 4. 检查是否存在键: 使用`Contains()`方法检查哈希表是否包含特定键: ```csharp if (ht.Contains("key")) { ... } ``` 5. 清除所有元素: 使用`Clear()`方法移除哈希表中的所有元素: ```csharp ht.Clear(); ``` 6. 遍历哈希表: 可以通过`foreach`循环遍历哈希表中的所有键值对,使用`DictionaryEntry`对象: ```csharp foreach (DictionaryEntry de in ht) { Console.WriteLine("Key: " + de.Key + ", Value: " + de.Value); } ``` 7. 序列化与反序列化HashTable: 在C#中,可以使用`System.Xml.Serialization`命名空间的`XmlSerializer`类来实现对HashTable的序列化和反序列化。首先,我们需要定义一个类来承载我们的HashTable,然后使用`XmlSerializer`的`Serialize`和`Deserialize`方法。例如: ```csharp using System.IO; using System.Xml.Serialization; // 定义一个类来承载HashTable public class HashTableWrapper { [XmlElement("HashTable")] public Hashtable HashTable { get; set; } } // 序列化 XmlSerializer serializer = new XmlSerializer(typeof(HashTableWrapper)); using (StreamWriter writer = new StreamWriter("HashTable.xml")) { serializer.Serialize(writer, new HashTableWrapper() { HashTable = ht }); } // 反序列化 using (StreamReader reader = new StreamReader("HashTable.xml")) { HashTableWrapper wrapper = (HashTableWrapper)serializer.Deserialize(reader); Hashtable deserializedHt = wrapper.HashTable; } ``` 通过这些操作,我们可以方便地管理并序列化C#中的HashTable对象,从而在需要的时候恢复其状态。理解并熟练掌握这些基本操作对于处理动态数据存储和传输至关重要。
2006-02-23 上传
XML序列化这个东西挺搞人的,当你的Class里有Hashtable这样的东西的时候,在序列化的时候,在XmlSerializer serialize = new XmlSerializer(typeof(myClass));这一句上会出来一个“反射类型时出错”的错误。其实就是那个Hashtable在搞鬼,直接把上面一句换成XmlSerializer serialize = new XmlSerializer(typeof(Hashtable));罪魁祸首就出来了。这次是:“不支持类型 System.Collections.Hashtable,因为它实现 IDictionary”。原来XML序列化时对集合类还有一些比较特殊的要求。  那先来看一个可以正常序列化的集合类――Arraylist:serialize = new XmlSerializer(typeof(ArrayList));在序列化过程中临时生成的文件中可以发现如下的语句: WriteStartElement(@"ArrayOfAnyType", @""); for (int ia = 0; ia < a.Count; ia++) { Write1_Object(@"anyType", @"", ((System.Object)a[ia]), true, false); }WriteEndElement();对于集合类,在XML序列化过程中都是要如上所述来写XML的,显然的,对于实现了IDictionary接口的集合来讲,上面那个for循环是走不通的。因为对于IDictionary来讲Item属性(也就是C#里的[]这个东西,也叫索引器,名字反正有点乱啦)是这样定义的:[C#]object this[ object key] {get; set;} object this[ object key] {get; set;} 上面是从结果上看,猜想最终序列化的时候,集合类是要以上面那样的循环方式进行序列化的,而实现了IDictionary接口的类对于那样的方式是不灵的,所以在生成临时文件的时候就不让它生成了,反正生成的DLL也是无法运行的,直接一个异常出来了。 其实在SDK上可以查到,关于XML序列化有这么一段:XmlSerializer 可以以不同方式处理实现 IEnumerable 或 ICollection 的类(条件是这些类满足某些要求)。实现 IEnumerable 的类必须实现带单个参数的公共 Add 方法。Add 方法的参数必须与从 GetEnumerator 方法返回的 IEnumerator.Current 属性所返回的类型一致(多态)。除实现 IEnumerable 外还实现 ICollection 的类(如 CollectionBase)必须有一个取整数的公共 Item 索引属性(在 C# 中为索引器),并且它必须有一个整数类型的公共 Count 属性。传递给 Add 方法的参数必须与从 Item 属性返回的类型相同或与该类型的某个基的类型相同。对于实现 ICollection 的类,要序列化的值将从索引 Item 属性检索,而不是通过调用 GetEnumerator 来检索。另外请注意,除返回另一个集合类(实现 ICollection 的集合类)的公共字段之外,将不序列化公共字段和属性。无法满足上述条件的都会抛出相应的异常,而实现了IDictionary接口的类显然是无法满足的,.net在实现的时候,一开始就先判断是不是实现了IDictionary接口,发现实现了这个接口的直接就出来了,下面什么Add方法、Item属性呀都不管了。还有一点,就是l 类(Class这一级)――包括集合类与非集合,l 非集合类 需要序列化的属性里的访问方法(不用序列化的属性例外),l 在集合类里,上面提到过的Add方法,Item属性、Count属性、Current属性的访问方法等,如果有过SecurityAttribute声明的也是无法序列化的。不过现在写代码那个SecurityAttribute用得是甚少――这个方面的东西除了照例子依样画葫芦过一下在实践中根本是没有涉足。 要序列化Hashtable其实就只是少一个整数类型的Item属性而已,在这上面是没有什么办法了。想到SortedList这个东西很多方面跟Hashtable差不多,不过它还能依序取得集合中的元素,只是用的不是整数类型的Item属性,而是用GetByIndex()方法。所以就用它来偷梁换柱一下了。// [EnvironmentPermission(SecurityAction.Assert)] public class MyCollection : ICollection { private SortedList list = new SortedList(); public MyCollection () { } // [EnvironmentPermission(SecurityAction.Assert)] public void Add(Item item) { list.Add(item.ID,item); } public Item this[int index] { get {return (Item)list.GetByIndex(index);} } ICollection 成员#region ICollection 成员 public bool IsSynchronized { get { return false; } } public int Count { get { return list.Count; } }      [EnvironmentPermission(SecurityAction.Assert)] public void CopyTo(Array array, int index) { list.CopyTo(array,index); } public object SyncRoot { get { return this; } } #endregion IEnumerable 成员#region IEnumerable 成员 public IEnumerator GetEnumerator() { return list.GetEnumerator(); } #endregion}Item是自定义的一个类。没什么具体的意义。 这样偷一下,上面的这个MyCollection类就是可以被序列化的了,然后把SortedList其他属性包一下,就基本可以当成一个SortedList使用了,说它是Hashtable也差不多吧――外表基本看不出来。不过局限性还是有喽。它的Add方法的参数,与Item属性的类型必须是强类型的,不能用Objcet。用Object类型,临时文件是可以生成,serialize = new XmlSerializer(typeof(Myclass)); 这一句是可以通过没异常了。但真正序列化的时候,除非是一些基本的数据类型,否则它不知道如何去把那个类型写成相应的String,写XML文件就出错了