'已添加具有相同密钥的项目。' - 哪个键?

时间:2017-07-05 05:03:10

标签: .net visual-studio

以下代码:

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社区版。

2 个答案:

答案 0 :(得分:4)

我不相信使用当前桌面.NET框架从异常中获取该信息是可行的。 (虽然你可以do it in the debugger,但如果你愿意跳过一些箍。)

好消息是,在.NET Core中,您可以看到密钥,正如您可以通过以下源代码看到的那样:

因此,在.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>。据推测,尝试的密钥可以以类似的方式找到其他字典类型:

  1. Enable .NET Framework Source debugging。这些说明似乎仍然有效,即使它们适用于Visual Studio 2013.(注意:我必须清除符号缓存。)

  2. 异常(至少对于此代码而言)将在the following line抛出:

    throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)));
    
  3. 将调用堆栈中的一级向上追溯到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);
            }
    
  4. 大多数局部变量都不可用 - Watch和Local窗口提供以下消息:

      

    无法获取局部变量或参数的值,因为它在此指令指针处不可用,可能是因为它已被优化掉。

    但是i可用,entries也是如此。 Watch窗口中的以下表达式返回重复键:

    entries[i].key