2

Suppose we have a source IEnumerable sequence:

IEnumerable<Tuple<int, int>> source = new [] {
    new Tuple<int, int>(1, 2),
    new Tuple<int, int>(2, 3),
    new Tuple<int, int>(3, 2),
    new Tuple<int, int>(5, 2),
    new Tuple<int, int>(2, 0),
};

We want to apply some filters and some transformations:

IEnumerable<int> result1 = source.Where(t => (t.Item1 + t.Item2) % 2 == 0)
                                 .Select(t => t.Item2)
                                 .Select(i => 1 / i);
IEnumerable<int> result2 = from t in source
                           where (t.Item1 + t.Item2) % 2 == 0
                           let i = t.Item2
                           select 1 / i;

These two queries are equivalent, and both will throw a DivideByZeroException on the last item.

However, when the second query is enumerated, the VS debugger will let me inspect the entire query, thus very handy in determining the source of the problem.

VS Debugger is useful

However, there is no equivalent help when the first query is enumerated. Inspecting into the LINQ implementation yields no useful data, probably due to the binary being optimized:

LINQ is too optimized

Is there a way to usefully inspect the enumerable values up the "stack" of IEnumerables when not using query syntax? Query syntax is not an option because sharing code is impossible with it (ie, the transformations are non trivial and used more than once).

4

1 回答 1

1

但是你可以调试第一个。只需在任何一个 lambda 上插入断点,您就可以自由检查参数的值或范围内的任何其他内容。

在此处输入图像描述

调试时,您可以检查 (在第一个中断的情况下Where) t,t.Item1等的值。

在此处输入图像描述

至于在第二个查询中t执行最终查询时可以检查的原因select,而不是第一个查询,这是因为您还没有创建等效查询。您编写的第二个查询在由编译器写出时不会生成类似于您的第一个查询的内容。它将创造一些微妙但仍然显着不同的东西。它将创建如下内容:

IEnumerable<int> result1 = source.Where(t => (t.Item1 + t.Item2) % 2 == 0)
                        .Select(t => new
                        {
                            t,
                            i = t.Item2,
                        })
                        .Select(result => 1 / result.i);

let调用不只是选择该值,就像您编写的第一个查询那样。它选择一个新的匿名类型,从let子句中提取值以及先前的值,然后修改后续查询以提取适当的变量。这就是为什么“以前的”变量(即t在查询结束时仍在范围内(在编译时和运行时;仅此一项就应该对您有很大的提示)。使用我上面提供的查询,当中断select,可以result.t通过调试器看到 的值。

于 2013-08-26T17:49:53.747 回答