有个部落

一晃就半个十年,思念如潮...
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

泛型跟KeyNotFoundException

Posted on 2009-08-29 00:32  Leo.W  阅读(391)  评论(0编辑  收藏  举报

IDictionary<K, V> Dictionary<K, V> 相比非范型版本一个很大的变化是当指定的键不存在时索引器的处理逻辑。对 IDictionary Hashtable 来说,值的存储类型是 object,当键不存在时,索引器将返回 null,当键存在而对应值为 null 的话也返回 null(设计者可能认为调用者通常关心的是值是不是有效,而不是区分这两种情况)。然而,对于范型版本来说,因为存储的可能是值类型,所以不可以返回 null 来作为键不存在的标识。因此, IDictionary<K, V>Dictionary<K, V> 的索引器在指定键不存在的情况下将抛出 KeyNotFoundException 异常。这将导致源代码级别的不兼容,也就是说,以下的代码在存储值类型的情况下将不可移植,而必须改写(例如先使用 ContainsKey 方法判断指定键是否存在,然后再访问;或者使用不抛出异常的 TryGetValue 方法):

 

 

Hashtable map = ...;

if (map[“s1”] == null) { // 如果是范型版本将抛出异常而不是返回null

...

}

 

 

这一问题反映了设计者在最初设计 Hashtable 类的时候考虑的并不是很周到——使用了魔术值 null,既可以是指键不存在的情况,也可以是键存在而值为 null 的情况,而这一点对范型是不成立的。另外,从 Design By Contract 的角度讲,当指定键值不存在时,抛出异常是很自然的事情(与是否使用范型无关),就像数组越界一样。估计原设计者主要是从性能角度考虑才使用了 null 而不是异常处理。