`
pcajax
  • 浏览: 2111656 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

4.9 利用对应的泛型替换Hashtable[转]

阅读更多

 

 
  • 摘要:《C#3.0cookbook中文版》《C#3.0cookbook中文版》本书侧重于解决C#程序员在开发应用程序时遇到的各类问题,并以此组织全书内容。这些解决方案称为秘诀;每个秘诀都包含一个问题,他的解决方案及相关信息的讨论。 本节为大家介绍的是利用对应的泛型替换Hashtable。
  • 标签:泛型  C#3.0  0cookbook  C#3.0cookbook中文版
  • <script src="http://www.51cto.com/js/article/keywords_ad.js"></script>

4.9 利用对应的泛型替换Hashtable

问题

你希望通过用其泛型版本替换所有的Hashtable对象来增强应用程序的性能,并使得代码更容易处理。

解决方案

利用类型安全的泛型类System.Collections.Generic.Dictionary替换出现的所有System.Collections.Hashtable类。

下面给出了一个使用System.Collections.Hashtable对象的简单示例:

public static void UseNonGenericHashtable()
{
Console.WriteLine("\r\nUseNonGenericHashtable");
// Create and populate a Hashtable
Hashtable numbers = new Hashtable()
{ {1, "one"},"one"}, // Causes a boxing operation to occur for the key
{2, "two"} }; // Causes a boxing operation to occur for the key
// Display all key/value pairs in the Hashtable
// Causes an unboxing operation to occur on each iteration for the key
foreach (DictionaryEntry de in numbers)
{
Console.WriteLine("Key: " + de.Key + "\tValue: " + de.Value);
}
Console.WriteLine(numbers.IsReadOnly);
Console.WriteLine(numbers.IsFixedSize);
Console.WriteLine(numbers.IsSynchronized);
Console.WriteLine(numbers.SyncRoot);
numbers.Clear();
}
下面给出了使用System.Collections.Generic.Dictionary<T,U>对象的相同代码:
public static void UseGenericDictionary()
{
Console.WriteLine("\r\nUseGenericDictionary");
// Create and populate a Dictionary
Dictionary<int, string> numbers = new Dictionary<int, string>()
{ { 1, "one" }, { 2, "two" } };
// Display all key/value pairs in the Dictionary
foreach (KeyValuePair<int, string> kvp in numbers)
{
Console.WriteLine("Key: " + kvp.Key + "\tValue: " + kvp.Value);
}
Console.WriteLine(((IDictionary)numbers).IsReadOnly);
Console.WriteLine(((IDictionary)numbers).IsFixedSize);
Console.WriteLine(((IDictionary)numbers).IsSynchronized);
Console.WriteLine(((IDictionary)numbers).SyncRoot);
numbers.Clear();
}

讨论

对于应用程序中Hashtable的简单实现,这种替换应该相当容易。不过,有一些事情要注意。例如,泛型类Dictionary没有实现ICloneable接口,而Hashtable类则实现了该接口。

表4-3显示了两个类中同时实现的等价成员。

表4-3:Hashtable和泛型类Dictionary中的等价成员

Hashtable类中的成员 泛型类Dictionary中的等价成员
Comparer属性
Count属性 Count属性
IsFixedSize属性 ((IDictionary)myDict).IsFixedSize
IsReadOnly属性 ((IDictionary)myDict).IsReadOnly
IsSynchronized属性 ((IDictionary)myDict).IsSynchronized
Item属性 Item属性
Keys属性 Keys属性
SyncRoot属性 ((IDictionary)myDict).SyncRoot
Values属性 Values属性
Add方法 Add方法
Clear方法 Clear方法
Clone方法 使用重载的构造函数,它接受一个IDictionary<T,U>类型
Contains方法 ContainsKey方法
ContainsKey方法 ContainsKey方法
ContainsValue方法 ContainsValue方法
CopyTo方法 ((ICollection)myDict).CopyTo(arr,0)

表4-3:Hashtable和泛型类Dictionary中的等价成员(续)

Hashtable类中的成员 泛型类Dictionary中的等价成员
Remove方法 Remove方法
Synchronized静态方法 lock(myDictionary.SyncRoot) {...}
 TryGetValue方法
在表4-3中,有些情况下在Hashtable的成员与泛型类Dictionary的成员之间没有一对一的关系。从属性开始,注意只有Count、Keys、Values和Item这些属性同时存在于两个类中。为了弥补Dictionary类中缺失的属性,可以强制转换到IDictionary。下面的代码显示了如何使用这些强制转换获得缺失的属性:
    Dictionary<int, string> numbers = new Dictionary<int, string>(); 
Console.WriteLine(((IDictionary)numbers).IsReadOnly);
Console.WriteLine(((IDictionary)numbers).IsFixedSize);
Console.WriteLine(((IDictionary)numbers).IsSynchronized);
Console.WriteLine(((IDictionary)numbers).SyncRoot);

注意: 由于没有代码能够返回泛型Dictionary的同步版本,IsSynchronized属性将总是返回false。SyncRoot属性将总是返回调用它的相同对象。实质上,这个属性返回this指针。Microsoft决定取消从任何泛型集合类创建同步包装器的能力。

作为替代,他们建议使用lock关键字来锁定整个集合或者适合你的需要的另一类同步对象。

由于泛型类Dictionary中也缺失Clone方法(这是由于这个类没有实现ICloneable接口),可以代之以使用重载的构造函数,它接受一个IDictionary<T,U>类型:

    // Create and populate a Dictionary
Dictionary<int, string> numbers = new Dictionary<int, string>()
{ { 1, "one" }, { 2, "two" } };
// Display all key/value pairs in the original Dictionary.
foreach (KeyValuePair<int, string> kvp in numbers)
{
Console.WriteLine("Original Key: " + kvp.Key + "\tValue: " + kvp.Value);
}
// Clone the Dictionary object.
Dictionary<int, string> clonedNumbers = new Dictionary<int, string>(numbers);
// Display all key/value pairs in the cloned Dictionary.
foreach (KeyValuePair<int, string> kvp in numbers)
{
Console.WriteLine("Cloned Key: " + kvp.Key + "\tValue: " + kvp.Value);
}
Dictionary类中还缺失了另外两个方法:Contains和CopyTo方法。可以很容易地在Dictionary类中复制Contains方法。在Hashtable类中,Contains方法和ContainsKey方法都会展示相同的行为;因此,可以简单地使用Dictionary类的ContainsKey方法来模拟Hashtable类的Contains方法:
    // Create and populate a Dictionary
Dictionary<int, string> numbers =
new Dictionary<int, string>()
{ { 1, "one" }, { 2, "two" } };
Console.WriteLine("numbers.ContainsKey(1) == " + numbers.ContainsKey(1));
Console.WriteLine("numbers.ContainsKey(3) == " + numbers.ContainsKey(3));
在Dictionary类中也很容易模拟CopyTo方法,但是它需要做更多一点的工作:
    // Create and populate a Dictionary
Dictionary<int, string> numbers =
new Dictionary<int, string>()
{ { 1, "one" }, { 2, "two" } };
// Display all key/value pairs in the Dictionary.
foreach (KeyValuePair<int, string> kvp in numbers)
{
Console.WriteLine("Key: " + kvp.Key + "\tValue: " + kvp.Value);
}
// Create object array to hold copied information from Dictionary object.
KeyValuePair<int, string>[] objs = new KeyValuePair<int, string>[numbers.Count];
// Calling CopyTo on a Dictionary
// Copies all KeyValuePair objects in Dictionary object to objs[]
((IDictionary)numbers).CopyTo(objs, 0);
// Display all key/value pairs in the objs[].
foreach (KeyValuePair<int, string> kvp in objs)
{
Console.WriteLine("Key: " + kvp.Key + "\tValue: " + kvp.Value);
}

对Dictionary对象调用CopyTo方法涉及建立一个KeyValuePair<T,U>对象的数组,在调用CopyTo方法之后,该数组最终将用于保存Dictionary对象内的所有KeyValuePair<T,U>对象。接下来,将Dictionary对象numbers强制转换成IDictionary类型,以便可以调用CopyTo方法。一旦调用了CopyTo方法,objs数组将包含原始numbers对象中的所有KeyValuePair<T,U>对象的副本。注意:使用foreach循环以与numbers对象相同的方式迭代objs数组。

参考

MSDN文档中的"System.Collections.Hashtable类"和"System.Collections.Generic. Dictionary类"主题。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics