「クイックウォッチ」ウィンドウでデバッグ中にラムダ式を使用できないのはなぜですか?
UPD:参照
http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspx
匿名メソッドのようなラムダ式は、実際には非常に複雑な獣です。 Expression
(.NET 3.5)を除外しても、キャプチャされた変数ではなく、複雑なlotが残ります。これは、それらを使用するコードを根本的に再構築します(what変数はコンパイラ生成クラスのフィールドになると考えられます)、少し煙とミラーがあります。
そのため、私はあなたがそれらを無駄に使用できないことに驚くことはありません-この魔法をサポートするlotのコンパイラー作業(および舞台裏での型生成)があります。
いいえ、ウォッチ/ローカル/イミディエイトウィンドウでラムダ式を使用することはできません。マークが指摘したように、これは非常に複雑です。ただし、このトピックについてもう少し詳しく説明します。
デバッガーで匿名関数を実行する際にほとんどの人が考慮していないのは、バキュームでは発生しないということです。匿名関数を定義して実行するまさにその行為は、コードベースの基礎となる構造を変えます。一般的に、特にイミディエイトウィンドウからコードを変更することは、非常に難しい作業です。
次のコードを検討してください。
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がデバッガーで実行されると、ブレーク行で停止します。ユーザーがウォッチウィンドウに次のように入力した場合を想像してください
(Func<int>)(() => v2);
これを適切に実行するには、デバッガー(またはより適切なEE)が変数v2のクロージャーを作成する必要があります。これは難しいですが、不可能ではありません。
EEにとってこれを本当に難しい仕事にしているのは、最後の行です。その行をどのように実行する必要がありますか?すべての意図と目的のために、匿名関数はv2変数を削除し、closure2.v2に置き換えました。したがって、最後のコード行は実際に読む必要があります
var v3 = closure1.v1 + closure2.v2;
しかし、実際にコードでこの効果を得るには、EEが実際にENCアクションであるコードの最後の行を変更する必要があります。この特定の例は可能ですが、シナリオの大部分はそうではありません。
さらに悪いことは、ラムダ式が新しいクロージャを作成してはならないことを実行することです。実際には元のクロージャーにデータを追加する必要があります。この時点で、制限ENCにまっすぐ進みます。
残念なことに、私の小さな例は、私たちが遭遇した問題の表面をほんの少しだけ掻いています。私はこのテーマに関する完全なブログ記事を書くと言い続け、できれば今週の週末に時間があるといいです。
イミディエイトウィンドウまたはウォッチウィンドウでラムダ式を使用することはできません。
ただし、 System.Linq.Dynamic式 を使用できます。これは、.Where( "Id = @ 0"、2)の形式を取ります。標準のLinqで使用できるすべてのメソッドがありません。また、ラムダ式の完全な能力はありませんが、それでも、何もないよりはましです!
未来が来ました!
ラムダ式のデバッグのサポートがVisual Studio 2015に追加されました (Preview執筆時点)。
Expression Evaluatorを書き直す必要があったため、ASP.NETのリモートデバッグ、イミディエイトウィンドウでの変数の宣言、動的変数の検査など、多くの機能が欠落しています。また、ネイティブ関数の呼び出しを必要とするラムダ式は現在サポートされていません。
visual Studio用の拡張イミディエイトウィンドウ(デバッグにはLinq、Lambda Exprを使用)
最高、パトリック
ラムダ式はデバッガーの式エバリュエーターではサポートされていません...式ではなくメソッド(または式ツリー)を作成するためにコンパイル時に使用されるので、驚くことはほとんどありません(表示を.NET 2に切り替えてReflectorを見てください)彼らを見て)。
また、もちろん、別の構造全体の層であるクロージャーを形成することもできます。
それでも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\nTheステートメントは終了しました。 "} 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 }
_
アイデアの著者は見つけることができます ここ
VS 2015ではこれが可能になりましたが、これは彼らが追加した新機能の1つです。
あなたの質問に答えるために、Visual Studio Program Managerがこれができない理由についての公式の説明を以下に示します。要するに、VSで実装するのは「本当に、本当に難しい」からです。ただし、この機能は現在進行中です(2014年8月に更新)。
あなたがそこにいる間にあなたの投票を追加してください!