"Hızlı izleme" penceresinde hata ayıklarken neden lambda ifadelerini kullanamıyorum?
UPD: ayrıca bakınız
http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspx
"Hızlı izleme" penceresinde hata ayıklarken neden lambda ifadelerini kullanamıyorum?
UPD: ayrıca bakınız
http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspx
Yanıtlar:
Anonim yöntemler gibi Lambda ifadeleri de aslında çok karmaşık yaratıklardır. Expression(.NET 3.5) dışlasak bile , bu hala çok fazla karmaşıklık bırakıyor , en azından yakalanan değişkenler değil, onları kullanan kodu temelde yeniden yapılandırıyor (değişkenler olarak düşündüğünüz şey, derleyici tarafından üretilen sınıflarda alanlara dönüşüyor) , biraz duman ve aynalarla.
Bu nedenle, onları boşta kullanamamanıza hiç şaşırmadım - bu sihri destekleyen çok sayıda derleyici çalışması (ve perde arkasında tür oluşturma) var.
Hayır, saat / yereller / hemen pencerede lambda ifadelerini kullanamazsınız. Marc'ın da belirttiği gibi, bu inanılmaz derecede karmaşık. Yine de konuya biraz daha dalmak istedim.
Çoğu insanın hata ayıklayıcıda anonim bir işlevi yürütürken düşünmediği şey, bunun bir boşlukta oluşmamasıdır. Anonim bir işlevi tanımlama ve çalıştırma eylemi, kod tabanının temel yapısını değiştirir. Genel olarak ve özellikle yakın pencereden kodu değiştirmek çok zor bir iştir.
Aşağıdaki kodu düşünün.
void Example() {
var v1 = 42;
var v2 = 56;
Func<int> func1 = () => v1;
System.Diagnostics.Debugger.Break();
var v3 = v1 + v2;
}
Bu özel kod, v1 değerini yakalamak için tek bir kapanış oluşturur. Anonim bir işlev, kapsamı dışında bildirilmiş bir değişken kullandığında, kapatma yakalama gereklidir. Tüm niyet ve amaçlar için v1 artık bu işlevde mevcut değildir. Son satır aslında aşağıdakine daha çok benziyor
var v3 = closure1.v1 + v2;
Örnek işlevi hata ayıklayıcıda çalıştırılırsa, Kesme satırında duracaktır. Şimdi, kullanıcının aşağıdakileri izleme penceresine yazıp yazmadığını hayal edin
(Func<int>)(() => v2);
Bunu düzgün bir şekilde yürütmek için hata ayıklayıcının (veya daha uygun bir şekilde EE'nin) v2 değişkeni için bir kapanış yaratması gerekir. Bu zor ama imkansız değil.
Bunu EE için gerçekten zor bir iş yapan şey, bu son satırdır. Bu satır şimdi nasıl çalıştırılmalıdır? Tüm amaç ve amaçlar için anonim işlev, v2 değişkenini sildi ve onu closure2.v2 ile değiştirdi. Dolayısıyla, son kod satırının gerçekten şu anda okuması gerekiyor
var v3 = closure1.v1 + closure2.v2;
Yine de bu etkiyi kodda elde etmek için EE'nin aslında bir ENC eylemi olan son kod satırını değiştirmesi gerekir. Bu özel örnek mümkün olsa da, senaryoların iyi bir kısmı mümkün değil.
Daha da kötüsü, lambda ifadesinin yeni bir kapanış yaratmaması gerektiğidir. Aslında orijinal kapanışa veri eklemesi gerekir. Bu noktada doğrudan ENC sınırlamalarına girersiniz.
Benim küçük örneğim maalesef karşılaştığımız sorunların sadece yüzeyini çiziyor. Bu konu hakkında tam bir blog yazısı yazacağımı söyleyip duruyorum ve umarım bu hafta sonu vaktim olur.
Immediate veya Watch pencerelerinde lambda ifadelerini kullanamazsınız.
Bununla birlikte , .Where ("Id = @ 0", 2) biçimini alan System.Linq.Dynamic ifadelerini kullanabilirsiniz - standart Linq'te kullanılabilen tüm yöntemlere sahip değildir ve lambda ifadelerinin gücü, ama yine de hiç yoktan iyidir!
.Any(string predicate), aşağıdaki gibi bir şey koyabilirsiniz: .Where("Id>2").Any()Watch Window veya Pin to Source. Bu harika!
Gelecek geldi!
Lambda ifadelerinde hata ayıklama desteği, Visual Studio 2015'e ( Yazma sırasında önizleme) eklenmiştir .
İfade Değerlendiricisinin yeniden yazılması gerekiyordu, pek çok özellik eksik: ASP.NET'te uzaktan hata ayıklama, Anında pencerede değişken bildirme, dinamik değişkenleri inceleme vb. Ayrıca yerel işlevlere çağrı gerektiren lambda ifadeleri şu anda desteklenmemektedir.
bu yardımcı olabilir: Visual Studio için Extended Immediate Window (Hata Ayıklamada Linq, Lambda Expr kullanın)
En iyi dileklerimle Patrick
Lambda ifadeleri hata ayıklayıcının ifade değerlendiricisi tarafından desteklenmez ... ki bu şaşırtıcı değildir çünkü derleme zamanında ifadeler yerine yöntemler (veya İfade Ağaçları) oluşturmak için kullanılırlar (ekran .NET 2'ye geçerek Reflector'a bir göz atın) onları gör).
Ayrıca, tabii ki, başka bir yapı katmanı olan bir kapanış oluşturabilirler.
Expressionağaç oluşturabilirler - bu bağlama bağlıdır.
VS 2015'te bunu şimdi yapabilirsiniz, bu ekledikleri yeni özelliklerden biridir.
Hala Visual Studio 2013 kullanmanız gerekiyorsa, paket yöneticisi konsolu penceresini de kullanarak hemen pencerede bir döngü veya lambda ifadesi yazabilirsiniz. Benim durumumda, işlevin en üstüne bir liste ekledim:
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()Fonksiyonum nerede :
private DbSet<T> _dbSet;
public virtual IList<T> GetAll()
{
List<T> list;
IQueryable<T> dbQuery = _dbSet;
list = dbQuery
.ToList<T>();
return list;
}
Burada şu hatayı almaya devam ettim, bu yüzden çeşitli depolardaki tüm öğeleri yazdırmak istedim:
InnerException {"DELETE ifadesi REFERENCE kısıtlaması \" FK_dbo.Department_dbo.RoleHierarchy_OranizationalRoleId \ "ile çelişti. Çakışma \" CC_Portal_SchoolObjectModel \ "veritabanında, tablo \" dbo.Department \ ", 'OranizationalRoleId' sütununda meydana geldi. ifade sonlandırıldı. "} System.Exception {System.Data.SqlClient.SqlException}
Ardından, hemen pencerede bunu çalıştırarak departman havuzunda kaç kayıt olduğunu buluyorum:
_unitOfWork.DepartmentRepository.GetAll().ToList().Count
243 döndü.
Bu nedenle, paket yöneticisi konsolunda aşağıdakileri yürütürseniz, tüm öğeleri yazdırır:
PM> for($i = 0; $i -lt 243; $i++) { $a = $dte.Debugger.GetExpression("departments[$i].OrgagnizationalRoleId"); Write-Host $a.Value $i }
Fikir yazarı burada bulunabilir
Sorunuzu yanıtlamak için, Visual Studio Program Yöneticisi'nin bunu neden yapamayacağınıza dair resmi açıklaması burada. Kısaca, çünkü VS'de uygulamak "gerçekten çok zor". Ancak özellik şu anda devam ediyor (Ağustos 2014'te güncellendi).
Hata ayıklama sırasında lambda ifadelerinin değerlendirilmesine izin verin
Oradayken oyunuzu ekleyin!