「クイックウォッチ」ウィンドウでデバッグ中にラムダ式を使用できないのはなぜですか?
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
回答:
いいえ、ウォッチ、ローカル、イミディエイトウィンドウでラムダ式を使用することはできません。マークが指摘したように、これは信じられないほど複雑です。ただし、このトピックについてもう少し詳しく説明したいと思いました。
デバッガで無名関数を実行する際にほとんどの人が考慮しないのは、それがバキュームで発生しないことです。匿名関数を定義して実行するという行為自体が、コードベースの基本構造を変更します。一般に、特にイミディエイトウィンドウからコードを変更することは、非常に困難な作業です。
次のコードを検討してください。
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のクロージャーを作成する必要があります。これは難しいですが、不可能ではありません。
EEにとってこれが本当に難しい仕事になるのは、その最後の行です。その行はどのように実行する必要がありますか?すべての意図と目的のために、無名関数はv2変数を削除し、それをクロージャ2.v2に置き換えました。したがって、コードの最後の行は本当に読む必要があります
var v3 = closure1.v1 + closure2.v2;
ただし、実際にコードでこの効果を得るには、実際にはENCアクションであるコードの最終行を変更する必要があります。この特定の例は可能ですが、シナリオの大部分は不可能です。
さらに悪いのは、ラムダ式が新しいクロージャーを作成してはならないということです。実際には、元のクロージャーにデータを追加する必要があります。この時点で、制限ENCにまっすぐ進みます。
私の小さな例は、残念なことに、私たちが遭遇する問題の表面をなぞっただけです。私はこの件について完全なブログ記事を書くつもりであり、うまくいけば私は今週末に時間があるであろう。
イミディエイトウィンドウまたはウォッチウィンドウでラムダ式を使用することはできません。
ただし、.Where( "Id = @ 0"、2)という形式のSystem.Linq.Dynamic式を使用することもできます。これには、標準のLinqで使用できるすべてのメソッドがなく、完全なメソッドもありません。ラムダ式の力ですが、それでも何もないよりはましです!
.Any(string predicate)
、あなたがすることができます:何か入れ.Where("Id>2").Any()
ソースにウォッチウィンドウ、またはピンでを。それは素晴らしい!
未来が来た!
ラムダ式のデバッグのサポートがVisual Studio 2015(執筆時のプレビュー)に追加されました。
式エバリュエーターを書き直す必要があったため、ASP.NETのリモートデバッグ、イミディエイトウィンドウでの変数の宣言、動的変数の検査など、多くの機能がありません。また、ネイティブ関数の呼び出しを必要とするラムダ式も現在サポートされていません。
これは役立つかもしれません:Visual Studioの拡張イミディエイトウィンドウ(デバッグにはLinq、Lambda Exprを使用)
最高です、パトリック
ラムダ式は、デバッガーの式エバリュエーターではサポートされていません...コンパイル時に式ではなくメソッド(または式ツリー)を作成するために使用されるため、これは驚くには当たりません(表示を.NET 2に切り替えてReflectorを確認してください)彼らを見て)。
もちろん、それらはクロージャーを形成することもできます。
Expression
木を作成するかもしれません-それは文脈に依存します。
VS 2015では、今すぐ実行できます。これは、彼らが追加した新機能の1つです。
それでも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 \ "、列 'OranizationalRoleId'。\ r \ nで発生しましたステートメントが終了しました。 "} 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 Program Managerの公式説明です。つまり、VSに実装するのは「本当に、本当に難しい」からです。ただし、この機能は現在進行中です(2014年8月に更新)。
そこにいる間に投票を追加してください!