在这个线程中
如何获取 null 而不是 KeyNotFoundException 按键访问 Dictionary 值?
在我自己的答案中,我使用显式接口实现来更改基本的字典索引器行为,KeyNotFoundException
如果字典中不存在键,则不会抛出(因为null
在这种情况下,我很容易获得正确的内联)。
这里是:
public interface INullValueDictionary<T, U>
where U : class
{
U this[T key] { get; }
}
public class NullValueDictionary<T, U> : Dictionary<T, U>, INullValueDictionary<T, U>
where U : class
{
U INullValueDictionary<T, U>.this[T key]
{
get
{
if (ContainsKey(key))
return this[key];
else
return null;
}
}
}
因为在一个真实的应用程序中我有一个字典列表,所以我需要一种方法来从集合中访问字典作为接口。我使用简单int
的索引器来访问列表的每个元素。
var list = new List<NullValueDictionary<string, string>>();
int index = 0;
//...
list[index]["somekey"] = "somevalue";
最简单的事情是做这样的事情:
var idict = (INullValueDictionary<string, string>)list[index];
string value = idict["somekey"];
当我决定尝试使用协方差特性来代替使用一组接口时提出的问题。所以我需要一个带有协变类型参数的接口才能使强制转换工作。我想到的第一件事是IEnumerable<T>
,所以代码看起来像这样:
IEnumerable<INullValueDictionary<string, string>> ilist = list;
string value = ilist.ElementAt(index)["somekey"];
一点也不好,除了ElementAt
索引器更糟糕。的索引器在List<T>
中定义IList<T>
,并且T
没有协变。
我该怎么办?我决定自己写:
public interface IIndexedEnumerable<out T>
{
T this[int index] { get; }
}
public class ExtendedList<T> : List<T>, IIndexedEnumerable<T>
{
}
好吧,几行代码(我什至不需要在里面写任何东西ExtendedList<T>
),它就可以按我的意愿工作:
var elist = new ExtendedList<NullValueDictionary<string, string>>();
IIndexedEnumerable<INullValueDictionary<string, string>> ielist = elist;
int index = 0;
//...
elist[index]["somekey"] = "somevalue";
string value = ielist[index]["somekey"];
最后的问题是:这种协变转换能否在不创建额外集合的情况下以某种方式实现?