• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

C#泛型秘诀(6)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
本系列文章翻译O'Reilly 出版的《C# Cookbook》一书中的片段,仅供学习交流使用

 

4.9 使用泛型创建只读集合

问题

您希望类中的一个集合里的信息可以被外界访问,但不希望用户改变这个集合。

解决方案

使用ReadOnlyCollection<T>包装就很容易实现只读的集合类。例子如,Lottery类包含了中奖号码,它可以被访问,但不允许被改变:

public class Lottery
 

Lottery有一个内部的List<int>,它包含了在构造方法中被填的中奖号码。有趣的部分是它有一个公有属性叫Results,通过返回的ReadOnlyCollection<int>类型可以看到其中的中奖号码,从而使用户通过返回的实例来使用它。

如果用户试图设置集合中的一个值,将引发一个编译错误:

Lottery tryYourLuck = new Lottery();
    
// 打印结果.
    for (int i = 0; i < tryYourLuck.Results.Count; i++)
 

讨论

ReadOnlyCollection的主要优势是使用上的灵活性,可以在任何支持IListIList<T>的集合中把它做为接口使用。ReadOnlyCollection还可以象这样包装一般数组:

int [] items = new int[3];
    items[
0]=0;
    items[
1]=1;
    items[
2]=2;
new ReadOnlyCollection<int>(items);
 

这为类的只读属性的标准化提供了一种方法,并使得类库使用人员习惯于这种简单的只读属性返回类型。

阅读参考

查看MSDN文档中的“IList”和“Generic IList”主题。


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

问题

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

解决方案

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

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

public static void UseNonGenericHashtable()
 

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

public static void UseGenericDictionary()
 

讨论

对于应用程序中简单的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<intstring> numbers = new Dictionary<intstring>();
    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<intstring> numbers = new Dictionary<intstring>();
    numbers.Add(
1"one");
    numbers.Add(
2"two");
    
// 显示原字典的键/值对.
    foreach (KeyValuePair<intstring> kvp in numbers)
 

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

 // 创建和填充字典.
    Dictionary<intstring> numbers = new Dictionary<intstring>();
    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类中被模拟,但需要做一些额外的工作:
    

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
c#学习体会:使用 ref 和 out 传递数组发布时间:2022-07-13
下一篇:
C#安装Windows服务需要“设置服务登录”发布时间:2022-07-13
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap