Чому я не можу використовувати лямбда-вирази під час налагодження у вікні “Швидкий перегляд”?
UPD: див. Також
http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspx
Чому я не можу використовувати лямбда-вирази під час налагодження у вікні “Швидкий перегляд”?
UPD: див. Також
http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspx
Відповіді:
Лямбда-вирази, як і анонімні методи, насправді дуже складні звірі. Навіть якщо ми виключаємоExpression
(.NET 3.5), це все одно залишає багато складності, не в останню чергу є захопленими змінними, які принципово реструктурують код, який їх використовує (те, що ви вважаєте змінними, стають полями в класах, створених компілятором) , з трохи диму та дзеркал.
Таким чином, я ні в якому разі не здивований, що ви не можете їх використовувати простою - є багато роботи з компіляторами (і типовими поколіннями), які підтримують цю магію.
Ні, ви не можете використовувати лямбда-вирази у годиннику / місцевих жителях / безпосередньому вікні. Як зазначав Марк, це надзвичайно складно. Хоча я хотів заглибитися трохи далі в тему.
Більшість людей не враховують, виконуючи анонімну функцію в налагоджувачі, це те, що вона не відбувається у вакуумі. Сам акт визначення та запуску анонімної функції змінює базову структуру основи коду. Зміна коду, загалом, і зокрема з безпосереднього вікна, є дуже складним завданням.
Розглянемо наступний код.
void Example() {
var v1 = 42;
var v2 = 56;
Func<int> func1 = () => v1;
System.Diagnostics.Debugger.Break();
var v3 = v1 + v2;
}
Цей конкретний код створює єдине закриття для захоплення значення v1. Захоплення закриття потрібно, коли анонімна функція використовує змінну, оголошену поза її сферою дії. Для всіх цілей і цілей v1 більше не існує в цій функції. Останній рядок насправді більше схожий на наступний
var v3 = closure1.v1 + v2;
Якщо функція Example працює в налагоджувачі, вона зупиниться на рядку Break. А тепер уявіть, якщо користувач набрав у вікно годинника наступне
(Func<int>)(() => v2);
Для того, щоб правильно виконати це, налагоджувачу (або більш доречному EE) потрібно буде створити закриття для змінної v2. Це важко, але не неможливо зробити.
Однак насправді це важка робота для ЕЕ - це останній рядок. Як тепер слід виконувати цей рядок? Для всіх намірів і цілей анонімна функція видалила змінну v2 і замінила її на closure2.v2. Тож останній рядок коду справді тепер потрібно прочитати
var v3 = closure1.v1 + closure2.v2;
Однак для того, щоб насправді отримати цей ефект у коді, потрібно, щоб EE змінив останній рядок коду, який насправді є дією ENC. Хоча цей конкретний приклад можливий, значна частина сценаріїв - ні.
Що ще гірше, виконуючи, що лямбда-вираз не повинен створювати нове закриття. Насправді це має бути додавання даних до початкового закриття. На цьому етапі ви впадаєте прямо в обмеження ENC.
Мій невеликий приклад, на жаль, лише подряплює поверхню проблем, з якими ми стикаємось. Я продовжую повторювати, що напишу повну публікацію в блозі на цю тему, і, сподіваюся, у мене буде час на ці вихідні.
Ви не можете використовувати лямбда-вирази у вікнах Безпосереднього або Дивитися.
Однак ви можете використовувати вирази System.Linq.Dynamic , які приймають форму .Where ("Id = @ 0", 2) - він не має повного набору методів, доступних у стандартній Linq, і не має повного потужність лямбда-виразів, але все-таки це краще, ніж ніщо!
.Any(string predicate)
, ви можете помістити щось на зразок: .Where("Id>2").Any()
у Вікно спостереження або Закріпити до джерела. Це чудово!
Майбутнє настало!
Підтримка налагодження лямбда-виразів додана до Visual Studio 2015 ( попередній перегляд на момент написання).
Expression Evaluator довелося переписати, тому бракує багатьох функцій: віддалена налагодження ASP.NET, оголошення змінних у вікні Immediate, перевірка динамічних змінних тощо. Також лямбда-вирази, які вимагають викликів власних функцій, наразі не підтримуються.
це може допомогти: Розширене негайне вікно для Visual Studio (використовуйте Linq, Lambda Expr у налагодженні)
Все найкраще, Патріку
Лямбда-вирази не підтримуються оцінювачем виразів налагоджувача ... що навряд чи дивно, оскільки під час компіляції вони використовуються для створення методів (або дерев виразів), а не виразів (подивіться в Reflector, дисплей переключений на .NET 2 до бачити їх).
Плюс, звичайно, вони могли б утворити закриття, ще один цілий шар структури.
Expression
дерева - це залежить від контексту.
У VS 2015 ви можете зробити це зараз, це одна з нових функцій, яку вони додали.
Якщо вам все-таки потрібно використовувати Visual Studio 2013, ви можете фактично написати цикл або лямбда-вираз у безпосередньому вікні, використовуючи також вікно консолі менеджера пакетів. У моєму випадку я додав список у верхній частині функції:
private void RemoveRoleHierarchy()
{
#if DEBUG
var departments = _unitOfWork.DepartmentRepository.GetAll().ToList();
var roleHierarchies = _unitOfWork.RoleHierarchyRepository.GetAll().ToList();
#endif
try
{
//RoleHierarchy
foreach (SchoolBo.RoleHierarchy item in _listSoRoleHierarchy.Where(r => r.BusinessKeyMatched == false))
_unitOfWork.RoleHierarchyRepository.Remove(item.Id);
_unitOfWork.Save();
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
throw;
}
}
Де моя GetAll()
функція:
private DbSet<T> _dbSet;
public virtual IList<T> GetAll()
{
List<T> list;
IQueryable<T> dbQuery = _dbSet;
list = dbQuery
.ToList<T>();
return list;
}
Тут я постійно отримував таку помилку, тому хотів роздрукувати всі елементи в різних сховищах:
InnerException {"Оператор DELETE конфліктує з обмеженням REFERENCE \" FK_dbo.Department_dbo.RoleHierarchy_OranizationalRoleId \ ". Конфлікт стався в базі даних \" CC_Portal_SchoolObjectModel \ ", таблиці \" dbo.Department \ ", column \ Odrani \ n \ Oderani \". оператор припинено. "} System.Exception {System.Data.SqlClient.SqlException}
Потім я дізнаюся, скільки записів знаходиться у сховищі відділу, виконавши це в безпосередньому вікні:
_unitOfWork.DepartmentRepository.GetAll().ToList().Count
Який повернув 243.
Отже, якщо ви виконаєте наступне в консолі менеджера пакетів, він роздрукує всі елементи:
PM> for($i = 0; $i -lt 243; $i++) { $a = $dte.Debugger.GetExpression("departments[$i].OrgagnizationalRoleId"); Write-Host $a.Value $i }
Автора ідеї можна знайти тут
Щоб відповісти на ваше запитання, ось офіційне пояснення менеджера програми Visual Studio, чому ви не можете цього зробити. Коротше кажучи, тому що "це дійсно, дуже важко" впровадити у VS. Але ця функція наразі триває (оновлена в серпні 2014 року).
Дозволити оцінку лямбда-виразів під час налагодження
Додайте свій голос, поки ви там!