2011-01-24 2 views
14

У меня есть функция с лямбда-выражение что-то вроде:функции # Debugging C, которые содержат лямбда-выражения

int maxOccurrences = (from field in data select field).Max(f => f.Occurrences) 

P.S. Я уверен, что есть более симпатичная/более аккуратная/более идиоматическая версия вышеупомянутого утверждения, было бы неплохо узнать, что это может быть, хотя это не важно для вопроса!

Если я изменить что-нибудь еще в функции во время отладки сказать Console.Write выражение, отладчик состояний:

модифицирования «метод», который содержит лямбда-выражение предотвратит сеанс отладки продолжать то время как Изменить и продолжить включен.

Мне было интересно, почему это может быть так?

Я бы подумал, что IL, сгенерированный для функции lamba и оператора Console.Write, будет отдельным и что отладчик может изменять и изменять, когда это необходимо. Есть ли какая-то фундаментальная концепция, которую я теряю в отношении функциональности lamda?

ответ

11

Не может быть невозможно добиться во всех случаях (я не думаю). Тем не менее, это будет особенность монстра.

Когда у вас есть синтаксис LINQ в вашем методе, как правило, что включает в себя некоторые анонимный метод, либо за кадром:

// This LINQ query... 
var fields = from field in data select field; 

// ...is equivalent to this: 
var fields = data.Select(f => f); 

... или перед сцены просто утончаются (как в вашем примере):

(from field in data select field).Max(f => f.Occurrences) // <- lambda 

анонимный метод, в свою очередь, будет скомпилирован в типа с методами экземпляра для поддержки код, который вы написали.

В приведенном выше примере рассмотрите лямбда f => f.Occurrences. Это скомпилируется в тип с одним полем экземпляра, тип которого соответствует локальному f в этой лямбда; этот тип содержит метод, который возвращает f.Occurrences.

Итак, когда код в конечном счете, перечисляется на результате вашего запроса LINQ, что происходит в том, что экземпляр этого сгенерированного компилятора типа строится для каждого field в data и один методе того типа, который был сгенерирован для поддержки f => f.Occurrences Вычисление лямбда вызывается для расчета Max.

Проблема с редактированием и продолжением заключается в том, что если в редактируемом методе происходит изменение лямбда-выражений, это требует изменения сгенерированных типов, что не является вариантом. Можно было бы подумать, что это все равно можно сделать в случае, когда ничего не меняется относительно самих лямбда-выражений; до тех пор, пока одни и те же локали захвачены, а анонимные методы не изменяются, должно быть возможно модифицировать метод с этими характеристиками при отладке, как и для «обычных» методов в VS.

Но, как вы можете видеть, генерация типов, используемая для поддержки анонимных методов в целом, и поэтому запросы LINQ специально добавляют большую сложность процессу редактирования и продолжения, а в многие случаи делают невозможным (поскольку он требует полного изменения генерируемых типов).

Я думаю, что было просто принято решение, что стоить стоимости разработки даже не стоит, пытаясь поддержать это поведение в ограниченных сценариях, где он мог бы гипотетически работать.

-3

Существует очень простой способ отладить выражение lamba. Преобразуйте его в анонимный метод, используя встроенный делегат. Просто. :)

+8

Если это так просто, вы должны предоставить пример кода;) помните, что это не просто для всех. – ForceMagic

+0

Я согласен с ForceMagic – Mastro

+0

Вы не можете использовать анонимный на месте с момента: «_availableTypeCache.FirstOrDefault (delegate (Type t) {return t;}) Выражение не может содержать анонимные методы« Вы должны отказаться от LINQ с var, который выходит за рамки вызова LINQ. –

1

Или вы можете просто перейти к Visual Studio 2015 :)

The «Изменить и продолжить» особенность в VS 2015 позволяет методы редактирования с лямбда-выражения.

Вы можете прочитать об этом более подробно здесь:

http://blogs.msdn.com/b/visualstudioalm/archive/2015/04/29/net-enc-support-for-lambdas-and-other-improvements-in-visual-studio-2015.aspx

Смежные вопросы