Sen*_*ncy 4 .net c# dictionary
Take the following piece of code
var dictionary = new Dictionary<string, int>
{
["A"] = 1,
["B"] = 2,
["C"] = 3,
};
var dictionaryx = (IDictionary)dictionary;
var x = dictionaryx["X"]; // return null
var y = dictionary["Y"]; // throws KeyNotFoundException
Run Code Online (Sandbox Code Playgroud)
It is interesting to see the element access through the indexer leads to two different behaviours in x and y.
As in general, interfaces should give access to the same internal implementation. but in this case, it is different.
what is the catch here?
那是因为Dictionary<TKey, TValue>同时实现了 的通用版本IDictionary<TKey, TValue>和非通用版本(只是IDictionary产生了一个Object)。
查看源代码,您可以轻松看到通用版本的索引器在找不到键时显式抛出:
public TValue this[TKey key]
{
get
{
int i = FindEntry(key);
if (i >= 0) return entries[i].value;
ThrowHelper.ThrowKeyNotFoundException(); // <-- this line
return default(TValue);
}
}
Run Code Online (Sandbox Code Playgroud)
但非通用版本不会:
object IDictionary.this[object key]
{
get
{
if (IsCompatibleKey(key))
{
int i = FindEntry((TKey)key);
if (i >= 0)
return entries[i].value;
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,除非您明确地将您Dictionary的版本强制转换为非通用版本,否则您将调用在找不到键时抛出的索引器。
更新(根据您的评论):
由于IDictionary(非泛型版本)是在 .NET 1.0 中引入的(当时还不支持泛型),它消耗和返回的唯一类型显然是System.Object(可以对其进行测试null)。
因此,在找不到密钥时不抛出是有意义的,因为可以简单地这样做:
dict["nonExistingKey"] != null
Run Code Online (Sandbox Code Playgroud)
但是,一旦IDictionary<TKey, TValue>引入了泛型, theTValue也可以设置为值类型(如int或DateTime),并且必须将上述模式调整为:
var dict = new Dictionary<string, int>();
dict["nonExistingKey"] != 0;
dict["nonExistingKey"] != default(int);
Run Code Online (Sandbox Code Playgroud)
哪个更不流畅,更不标准,使用起来更麻烦。
从“设计角度”来看,我认为他们决定保留向后兼容性,IDictionary同时主动推出通用版本。
| 归档时间: |
|
| 查看次数: |
85 次 |
| 最近记录: |