以下代码:
var rnd = new Random();
Enumerable.Range(1,20).Select(x => rnd.Next(10)).ToDictionary(x => x, x => "");
将不可避免地失败,但有以下例外:
System.ArgumentException :'已添加具有相同键的项目。'
有没有办法在调试时使用Visual Studio IDE来查找尝试的密钥?密钥是否存储在异常详细信息中 - 某些内部/私有字段可能;哪个可以使用异常详细信息窗口读取?
我无法更改ToDictionary
的来源,以便将该密钥包含在抛出的异常中。
注意:我知道我可以使用For Each
循环而不是LINQ以可调试的方式重写它。但我问一般情况 - 当抛出此异常,并且源代码不在我的控制之下时,是否有某种方法可以访问密钥?
使用VS 2017社区版。
答案 0 :(得分:4)
我不相信使用当前桌面.NET框架从异常中获取该信息是可行的。 (虽然你可以do it in the debugger,但如果你愿意跳过一些箍。)
好消息是,在.NET Core中,您做可以看到密钥,正如您可以通过以下源代码看到的那样:
Dictionary.Add
Dictionary.TryInsert
ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException
SR.Argument_AddingDuplicateWithKey
因此,在.NET Core上,您最终会遇到如下异常:
System.ArgumentException: An item with the same key has already been added. Key: x
我不相信你可以以编程方式确定此时的密钥,但至少你可以告诉调试目的,假设你的密钥的字符串表示足够详细。
我希望在某些时候这可能会成为.NET的桌面版本。
答案 1 :(得分:0)
可以使用IDE,至少可以使用System.Collections.Generic.Dictionary<TKey,TValue>
。据推测,尝试的密钥可以以类似的方式找到其他字典类型:
Enable .NET Framework Source debugging。这些说明似乎仍然有效,即使它们适用于Visual Studio 2013.(注意:我必须清除符号缓存。)
异常(至少对于此代码而言)将在the following line抛出:
throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)));
将调用堆栈中的一级向上追溯到this line,我进入下面的代码块:
for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next) {
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) {
if (add) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}
大多数局部变量都不可用 - Watch和Local窗口提供以下消息:
无法获取局部变量或参数的值,因为它在此指令指针处不可用,可能是因为它已被优化掉。
但是i
可用,entries
也是如此。 Watch窗口中的以下表达式返回重复键:
entries[i].key