Mengapa saya tidak dapat menggunakan ekspresi lambda saat melakukan debug di jendela "Jam tangan cepat"?
UPD: lihat juga
http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspx
Mengapa saya tidak dapat menggunakan ekspresi lambda saat melakukan debug di jendela "Jam tangan cepat"?
UPD: lihat juga
http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspx
Jawaban:
Ekspresi lambda, seperti metode anonim, sebenarnya adalah makhluk yang sangat kompleks. Bahkan jika kita mengesampingkan Expression
(.NET 3.5), itu masih menyisakan banyak kompleksitas, paling tidak variabel yang ditangkap, yang secara fundamental menyusun ulang kode yang menggunakannya (apa yang Anda anggap sebagai variabel menjadi bidang pada kelas yang dihasilkan kompiler) , dengan sedikit asap dan cermin.
Karena itu, saya tidak sedikit pun terkejut bahwa Anda tidak dapat menggunakannya dengan santai - ada banyak pekerjaan kompilator (dan pembuatan tipe di belakang layar) yang mendukung keajaiban ini.
Tidak, Anda tidak dapat menggunakan ekspresi lambda di jendela jam tangan / lokal / langsung. Seperti yang ditunjukkan Marc, ini sangat kompleks. Saya ingin menyelami topik ini lebih jauh.
Apa yang kebanyakan orang tidak pertimbangkan dengan menjalankan fungsi anonim di debugger adalah bahwa hal itu tidak terjadi dalam vakum. Tindakan mendefinisikan dan menjalankan fungsi anonim mengubah struktur yang mendasari basis kode. Mengubah kode, secara umum, dan khususnya dari jendela langsung, adalah tugas yang sangat sulit.
Perhatikan kode berikut.
void Example() {
var v1 = 42;
var v2 = 56;
Func<int> func1 = () => v1;
System.Diagnostics.Debugger.Break();
var v3 = v1 + v2;
}
Kode khusus ini membuat penutupan tunggal untuk menangkap nilai v1. Tangkapan penutupan diperlukan setiap kali fungsi anonim menggunakan variabel yang dideklarasikan di luar cakupannya. Untuk semua maksud dan tujuan v1 tidak lagi ada dalam fungsi ini. Baris terakhir sebenarnya lebih terlihat seperti berikut
var v3 = closure1.v1 + v2;
Jika Contoh fungsi dijalankan di debugger itu akan berhenti di baris Break. Sekarang bayangkan jika pengguna mengetik berikut ini ke dalam jendela arloji
(Func<int>)(() => v2);
Untuk menjalankan ini dengan benar, debugger (atau lebih tepat EE) perlu membuat penutupan untuk variabel v2. Ini sulit tetapi bukan tidak mungkin untuk dilakukan.
Apa yang benar-benar membuat ini menjadi pekerjaan yang sulit bagi EE adalah baris terakhir itu. Bagaimana seharusnya baris itu sekarang dieksekusi? Untuk semua maksud dan tujuan, fungsi anonim menghapus variabel v2 dan menggantinya dengan closure2.v2. Jadi baris terakhir kode sekarang benar-benar perlu dibaca
var v3 = closure1.v1 + closure2.v2;
Namun untuk benar-benar mendapatkan efek ini dalam kode, EE harus mengubah baris terakhir kode yang sebenarnya merupakan tindakan ENC. Meskipun contoh khusus ini dimungkinkan, sebagian besar skenario tidak.
Yang lebih buruk lagi adalah mengeksekusi ekspresi lambda itu seharusnya tidak membuat penutupan baru. Ini seharusnya benar-benar menambahkan data ke penutupan asli. Pada titik ini Anda langsung menuju ke batasan ENC.
Contoh kecil saya sayangnya hanya menggores permukaan dari masalah yang kita hadapi. Saya terus mengatakan saya akan menulis posting blog lengkap tentang hal ini dan semoga saya punya waktu akhir pekan ini.
Anda tidak dapat menggunakan ekspresi lambda di jendela Immediate atau Watch.
Namun Anda dapat menggunakan ekspresi System.Linq.Dynamic , yang berbentuk .Where ("Id = @ 0", 2) - tidak memiliki berbagai metode lengkap yang tersedia dalam Linq standar, dan tidak memiliki kekuatan ekspresi lambda, tapi tetap saja, itu lebih baik daripada tidak sama sekali!
.Any(string predicate)
, Anda dapat meletakkan sesuatu seperti: .Where("Id>2").Any()
di Jendela Tonton, atau Sematkan ke Sumber. Itu bagus!
Masa depan telah datang!
Dukungan untuk debugging ekspresi lambda telah ditambahkan ke Visual Studio 2015 ( Pratinjau pada saat penulisan).
Expression Evaluator harus ditulis ulang, begitu banyak fitur yang hilang: ASP.NET debugging jarak jauh, mendeklarasikan variabel di jendela Immediate, memeriksa variabel dinamis, dll. Juga ekspresi lambda yang memerlukan panggilan ke fungsi asli saat ini tidak didukung.
ini mungkin membantu: Extended Immediate Window for Visual Studio (gunakan Linq, Lambda Expr dalam Debugging)
Semua yang terbaik, Patrick
Ekspresi lambda tidak didukung oleh penilai ekspresi debugger ... yang tidak mengherankan karena pada waktu kompilasi mereka digunakan untuk membuat metode (atau Pohon Ekspresi) daripada ekspresi (lihat di Reflektor dengan tampilan yang dialihkan ke .NET 2 ke Lihat mereka).
Ditambah tentu saja mereka bisa membentuk penutup, seluruh lapisan struktur lainnya.
Expression
pohon - tergantung pada konteksnya.
Di VS 2015 Anda dapat melakukannya sekarang, ini adalah salah satu fitur baru yang mereka tambahkan.
Jika Anda masih perlu menggunakan Visual Studio 2013, Anda sebenarnya dapat menulis loop, atau ekspresi lambda di jendela langsung menggunakan juga jendela konsol manajer paket. Dalam kasus saya, saya menambahkan daftar di bagian atas fungsi:
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;
}
}
Dimana GetAll()
fungsi saya adalah:
private DbSet<T> _dbSet;
public virtual IList<T> GetAll()
{
List<T> list;
IQueryable<T> dbQuery = _dbSet;
list = dbQuery
.ToList<T>();
return list;
}
Di sini saya terus mendapatkan kesalahan berikut, jadi saya ingin mencetak semua item di berbagai repositori:
InnerException {"Pernyataan DELETE berkonflik dengan batasan REFERENCE \" FK_dbo.Department_dbo.RoleHierarchy_OranizationalRoleId \ ". Konflik terjadi di database \" CC_Portal_SchoolObjectModel \ ", table \" dbo.Department \ ", kolom 'OranizationalRoleId \" pernyataan telah dihentikan. "} System.Exception {System.Data.SqlClient.SqlException}
Kemudian, saya mencari tahu berapa banyak record yang ada di repositori departemen dengan menjalankan ini di jendela langsung:
_unitOfWork.DepartmentRepository.GetAll().ToList().Count
Yang mengembalikan 243.
Jadi, jika Anda menjalankan perintah berikut di konsol pengelola paket, semua item akan dicetak:
PM> for($i = 0; $i -lt 243; $i++) { $a = $dte.Debugger.GetExpression("departments[$i].OrgagnizationalRoleId"); Write-Host $a.Value $i }
Penulis gagasan dapat ditemukan di sini
Untuk menjawab pertanyaan Anda, berikut ini penjelasan resmi Visual Studio Program Manager tentang mengapa Anda tidak dapat melakukan ini. Singkatnya, karena "sangat, sangat sulit" untuk diterapkan di VS. Tetapi fitur tersebut sedang dalam proses (diperbarui pada Agustus 2014).
Izinkan evaluasi ekspresi lambda saat melakukan debug
Tambahkan suara Anda saat Anda di sana!