zoukankan      html  css  js  c++  java
  • 泛型系列<9>:使用相应的泛型版本替换Hashtable

    4.10 使用相应的泛型版本替换Hashtable

    问题

    您希望通过使用相应的泛型版本替换所有Hashtable来增强应用程序性能并使得代码更为易读。当您发现这些数据结构中存放结构体和值类型会导致装箱/拆箱操作,这就变得非常有必要了。

    解决方案

    替换所有已存在的System.Collections.Hashtable类为速度更快的System.Collections.Generic.Dictionary泛型类。

    这有一个使用System.Collections.Hashtable对象的简单例子:

    public static void UseNonGenericHashtable()

        {

            // 创建并填充一个Hashtable.

            Hashtable numbers = new Hashtable();

            numbers.Add(1, "one");    // 键会导致装箱操作

            numbers.Add(2, "two");    // 键会导致装箱操作

     

            // 在Hashtable显示所有的键/值对.

            // 在每次迭代中都会因为键导致一个拆箱操作

            foreach (DictionaryEntry de in numbers)

            {

                Console.WriteLine("Key: " + de.Key + "\tValue: " + de.Value);

            }

            numbers.Clear();

    }

    下面是相同的代码使用了System.Collections.Generic.Dictionary<T,U>对象:

    public static void UseGenericDictionary()

        {

            // 创建并填充字典.

            Dictionary<int, string> numbers = new Dictionary<int, string>();

            numbers.Add(1, "one");

            numbers.Add(2, "two");

            // 显示字典中的所有键值对.

            foreach (KeyValuePair<int, string> kvp in numbers)

            {

                Console.WriteLine("Key: " + kvp.Key + "\tValue: " + kvp.Value);

            }

            numbers.Clear();

    }

    讨论

    对于应用程序中简单的Hashtable实现,这种替换将十分容易。但有些地方需要注意,如泛型Dictionary类没有实现ICloneable接口,而Hashtable类实现了。

    4-2显示了两个类中的等价成员:

    4-2 Hashtable和泛型Dictionary类的等价成员

    Hashtable 类的成员

    泛型 Dictionary 类的相应成员

    N/A

    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)

    Remove方法

    Remove方法

    Synchronized static方法

    lock(myDictionary.SyncRoot) {…}

    N/A

    TRyGetValue方法

     

    4-2中,并非所有的HashtableDictionary的成员都一一对应。我们从属性开始,注意,只有CountKeysValuesItem属性在两个类中都存在。为了弥补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);

    注意,由于缺少返回一个泛型字典同步版本的代码,IsSynchronized属性将总是返回falseSyncRoot属性在被调用时总是返回相同的对象。实际上这个属性返回的是this指针。微软已经决定移除泛型集合类的创建同步包装的功能。

    做为替代,他们推荐使用lock关键字锁住整个集合或其他同步对象类型以满足您的需求。

    因为在泛型字典类中也缺少了克隆方法(实际是是因为这个类没有实现ICloneable接口),您可以转而使用重载的构造方法来接收一个IDictionary<T,U>类型:

        // 创建并填充字典.

        Dictionary<int, string> numbers = new Dictionary<int, string>();

        numbers.Add(1, "one");

        numbers.Add(2, "two");

        // 显示原字典的键/值对.

        foreach (KeyValuePair<int, string> kvp in numbers)

        {

            Console.WriteLine("Original Key: " + kvp.Key + "\tValue: " + kvp.Value);

        }

        // 克隆字典对象.

        Dictionary<int, string> clonedNumbers = new Dictionary<int, string>(numbers);

        // 显示克隆字典中的键/值对.

        foreach (KeyValuePair<int, string> kvp in numbers)

        {

            Console.WriteLine("Cloned Key: " + kvp.Key + "\tValue: " + kvp.Value);

    }

    还有两个Dictionary类中缺少的方法:ContainsCopyTo方法。Contains方法的功能在Dictionary类中很容易被实现。在Hashtable类中,Cintains方法和ContainsKey方法有相同的行为,因此您可以在Dictionary类中简单地使用ContainsKey方法来模拟Hashtable类中的Contains方法:

        // 创建和填充字典.

        Dictionary<int, string> numbers = new Dictionary<int, string>();

        numbers.Add(1, "one");

        numbers.Add(2, "two");

        Console.WriteLine("numbers.ContainsKey(1) == " + numbers.ContainsKey(1));

    Console.WriteLine("numbers.ContainsKey(3) == " + numbers.ContainsKey(3));

    CopyTo方法也很容易在Dictionary类中被模拟,但需要做一些额外的工作:

        // 创建和填充字典.

        Dictionary<int, string> numbers = new Dictionary<int, string>();

        numbers.Add(1, "one");

        numbers.Add(2, "two");

        // 显示字典中的所有键/值对.

        foreach (KeyValuePair<int, string> kvp in numbers)

        {

            Console.WriteLine("Key: " + kvp.Key + "\tValue: " + kvp.Value);

        }

        // 创建对象数组来拷贝字典对象中的信息.

        KeyValuePair<int, string>[] objs = new KeyValuePair<int,

    string>[numbers.Count];

        // 调用字典中的CopyTo方法

        // 把字典中的所有键/值对对象拷贝到objs中

        ((IDictionary)numbers).CopyTo(objs, 0);

        // 显示objs[]中的所有键/值对.

        foreach (KeyValuePair<int, string> kvp in objs)

        {

            Console.WriteLine("Key: " + kvp.Key + "\tValue: " + kvp.Value);

    }

    调用Dictionary对象中的CopyTo方法需要创建一个KeyValuePair<T,U>对象数组,它用于在CopyTo方法被调用之后,控制字典对象中的所有KeyValuePair<T,U>对象。接下来numbers字典对象被转换为IDictionary类型以调用CopyTo方法。一旦CopyTo方法被调用,objs数组将包含原numbers对象中的所有KeyValuePair<T,U>对象。注意objs数组迭代时使用了foreach循环,这点和numbers对象是相同的。

  • 相关阅读:
    Beta阶段团队项目开发篇章2
    Beta阶段团队项目开发篇章1
    Alpha阶段博客链接
    大学生对技术网站需求的调查问卷结果分析
    关于大学生对技术网站需求的问卷调查
    第十。。。三周嘞
    进入第十一周喽
    第十周了耶~
    第九周也要过去啦~~~
    第,八,周,啦
  • 原文地址:https://www.cnblogs.com/kakaliush/p/2271369.html
Copyright © 2011-2022 走看看