Outil de débogage Visual Studio" quick watch " et expressions lambda

93
demandé sur user2418306 2009-04-07 16:40:26

9 réponses

les expressions Lambda, comme les méthodes anonymes, sont en fait des bêtes très complexes. Même si nous excluons Expression (.NET 3.5), cela laisse encore un lot de complexité, notamment en étant des variables capturées, qui fondamentalement restructurer le code qui les utilise (ce que vous pensez que les variables deviennent des Champs sur les classes générées par compilateur), avec un peu de fumée et de miroirs.

en tant que tel, je ne suis pas du tout surpris que vous ne puissiez pas les utiliser idly - il y a un lot de travail de compilateur (et de génération de type dans les coulisses) qui soutient cette magie.

63
répondu Marc Gravell 2009-04-07 12:52:05

Non vous ne pouvez pas utiliser les expressions lambda dans la montre / locaux / fenêtre immédiate. Comme Marc l'a souligné c'est incroyablement complexe. Je voulais plonger un peu plus dans le sujet.

ce que la plupart des gens ne considèrent pas avec l'exécution d'une fonction anonyme dans le débogueur est qu'elle ne se produit pas dans un Vacuum. Le fait même de définir et d'exécuter une fonction anonyme modifie la structure sous-jacente de la base de code. Changer le code, en général, et en particulier à partir de la fenêtre immédiate, est une tâche très difficile.

considère le code suivant.

void Example() {
  var v1 = 42;
  var v2 = 56; 
  Func<int> func1 = () => v1;
  System.Diagnostics.Debugger.Break();
  var v3 = v1 + v2;
}

ce code particulier crée une seule fermeture pour capturer la valeur v1. La capture de fermeture est requise chaque fois qu'une fonction anonyme utilise une variable déclarée hors de son champ d'application. Pour toutes fins utiles, v1 n'existe plus dans cette fonction. La dernière ligne ressemble plutôt à la suivante

var v3 = closure1.v1 + v2;

si L'exemple de fonction est exécuté dans le débogueur, il s'arrêtera à la ligne de coupure. Maintenant, imaginez si l'utilisateur tapait ce qui suit dans la fenêtre de montre

(Func<int>)(() => v2);

pour bien exécuter ceci, le débogueur (ou plus approprié L'EE) devrait créer une fermeture pour la variable v2. C'est difficile, mais pas impossible à faire.

ce qui rend vraiment ce travail difficile pour L'EE est cependant cette dernière ligne. Comment devrait-ligne maintenant exécuté? À toutes fins utiles, la fonction anonymous a supprimé la variable v2 et l'a remplacée par closure2.v2. Donc la dernière ligne de code a vraiment besoin de lire

var v3 = closure1.v1 + closure2.v2;

pour obtenir cet effet en code, il faut que L'EE change la dernière ligne de code qui est en fait une action ENC. Bien que cet exemple précis soit possible, une bonne partie des scénarios ne le sont pas.

ce qui est encore pire, c'est d'exécuter cette lambda expression ne devrait pas créer une nouvelle fermeture. Il devrait en fait être annexer des données à la fermeture originale. À ce point, vous allez directement dans les limites ENC.

mon petit exemple ne fait malheureusement qu'effleurer la surface des problèmes que nous rencontrons. Je n'arrête pas de dire que je vais écrire un billet de blog complet sur ce sujet et j'espère que j'aurai du temps ce week-end.

90
répondu JaredPar 2015-08-26 13:05:46

vous ne pouvez pas utiliser les expressions lambda dans les fenêtres immédiate ou regarder.

vous pouvez cependant utiliser le système .Linq.Expressions dynamiques , qui prennent la forme .Où ("Id = @0", 2) - Il n'a pas la gamme complète de méthodes disponibles en Linq standard, et n'a pas la pleine puissance des expressions lambda, mais tout de même, c'est mieux que rien!

49
répondu stusherwin 2010-05-05 09:13:01

le futur est venu!

le support pour déboguer les expressions lambda a été ajouté à Visual Studio 2015 ( Preview at the time of writing).

Expression Evaluator a dû être réécrit, donc beaucoup de fonctionnalités sont manquantes: le débogage à distance ASP.NET, déclarer des variables dans la fenêtre immédiate, inspecter les variables dynamiques etc. Aussi les expressions lambda qui nécessitent des appels à les fonctions natives ne sont pas actuellement supportées.

20
répondu Athari 2014-11-12 21:23:33

cela pourrait aider: Fenêtre immédiate prolongée pour Visual Studio (utiliser Linq, Lambda Expr dans le débogage)

Tout le meilleur, Patrick

5
répondu Patrick Wolf 2009-04-16 19:16:40
Les expressions

Lambda ne sont pas supportées par l'évaluateur des expressions du débogueur... ce qui n'est guère surprenant car au moment de la compilation, ils sont utilisés pour créer des méthodes (ou des arborescences D'expressions) plutôt que des expressions (jetez un coup d'oeil dans Reflector avec l'affichage commuté sur .NET 2 pour les voir).

Plus bien sûr ils pourraient former une fermeture, une autre couche entière de la structure.

2
répondu Richard 2009-04-07 13:18:51

dans VS 2015 vous pouvez le faire maintenant,c'est l'une des nouvelles fonctionnalités qu'ils ont ajouté.

1
répondu loneshark99 2015-12-05 07:59:07

si vous avez encore besoin D'utiliser Visual Studio 2013, vous pouvez en fait écrire une boucle, ou une expression lambda dans la fenêtre immédiate en utilisant également la fenêtre console du gestionnaire de paquets. Dans mon cas, j'ai ajouté une liste en haut de la fonction:

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;
    }
}

où ma fonction GetAll() est:

private DbSet<T> _dbSet;

public virtual IList<T> GetAll()
{
    List<T> list;
    IQueryable<T> dbQuery = _dbSet;
    list = dbQuery
        .ToList<T>();

    return list;
}

Ici, j'ai continué à obtenir l'erreur suivante, donc je voulais imprimer tous les éléments dans les différents dépôts:

InnerException {"la SUPPRESSION de La déclaration en contradiction avec la RÉFÉRENCE de la contrainte \"FK_dbo.Department_dbo.RoleHierarchy_OranizationalRoleId\". Le conflit s'est produit dans la base de données \ " CC_Portal_SchoolObjectModel\", table \ " dbo.Département\", colonne "OranizationalRoleId".\r\nl'déclaration a été résilié."} Système.Exception {Système.Données.SqlClient.SqlException}

ensuite, je trouve le nombre de documents dans le dépôt du département en exécutant ceci dans la fenêtre immédiate:

_unitOfWork.DepartmentRepository.GetAll().ToList().Count

Qui a retourné 243.

donc, si vous exécutez ce qui suit dans la console du gestionnaire de paquets, il imprime tous les éléments:

PM> for($i = 0; $i -lt 243; $i++) { $a = $dte.Debugger.GetExpression("departments[$i].OrgagnizationalRoleId"); Write-Host $a.Value $i }

L'auteur de l'idée peut être trouvé ici

1
répondu user8128167 2016-12-02 11:49:53

pour répondre à votre question, voici l'explication officielle du directeur de programme de Visual Studio expliquant pourquoi vous ne pouvez pas faire cela. En bref, parce que "c'est vraiment, vraiment difficile" à mettre en œuvre dans VS. Mais la fonctionnalité est actuellement en cours (Mise à jour en août 2014).

permettre l'évaluation des expressions lambda lors du débogage

ajoutez votre vote pendant que vous y êtes!

1
répondu Francisco d'Anconia 2016-12-02 11:50:48