2014-01-08 43 views
0

我调试这行代码:调试外部调用Lambda表达式

var myDict = myEnumerable.ToDictionary(k => k.NumericValue, v => v.Display()); 

我得到一个ArgumentException (An item with the same key has already been added)

VS2012似乎没有提供关于k.NumericValue导致重复密钥的值的见解。

我当然可以通过编写一些额外的调试代码来获得重复键来解决这个问题,但是有没有办法直接从调试器中获取?

回答

2

你不会有ToDictionary的符号信息,而且我更怀疑.NET BCL是以调试模式编译的......所以不会。

当然,如果您编写自己的ToDictionary实施方案,您可以提供例外情况中的信息,或者可以在信息可用的地方中断。

虽然在技术上可能检查内存的各种状态以确定程序运行时的密钥是什么,但它将会变得更简单只需稍微更改代码即可诊断此问题问题。

+0

你说得对。如果Watch支持lambda表达式,这将是可能并且微不足道的,但是添加一行代码如myEnumerable.GroupBy(e => e.NumericValue,e => e.NumericValue).Where(grp => grp。 Count()> 1)。选择(grp => grp.First())'并检查结果。 –

+0

通常情况下,我只是改变了代码并继续前进,但该过程运行了很长一段时间,然后才遇到该情况,因此它让我考虑是否有更好的方法。如果可以在抛出ArgumentException的时候在调试器中检查'k',那就可以解决问题。 –

+0

@SimonBelanger你可以让调试器在lambda上中断,问题是lambda已经在抛出异常的时候完成执行,所以当出现异常时,通过拉姆达;在库代码中只有一个本地存储结果,因此您需要能够在ToDictionary的定义中检查该本地,这是无法完成的。 – Servy

0

Servy的回答是正确的问题我问。

解决方案是编写自定义代码进行调试。这是我写入的一个扩展方法,作为ToDictionary()的插入式替换,它引发了一个更有意义的异常。随意编辑和改进。

public static Dictionary<K,V> ToDictionaryDbg<T,K,V>(this IEnumerable<T> source, Func<T,K> key, Func<T,V> value) 
{ 
    if (source == null) return null; 

    Dictionary<K, V> result = new Dictionary<K, V>(); 

    foreach (var element in source) 
    { 
     K k = default(K); 
     V v = default(V); 

     try 
     { 
      k = key(element); 
      v = value(element); 
      result.Add(k, v); 
     } 
     catch (ArgumentException aex) 
     { 
      throw new ArgumentException("Could not add element with key " + k + ". See inner exception.", aex); 
     } 
    } 

    return result; 
}