Visual Studio debugging “quick watch” tool and lam

2019-01-03 13:36发布

9条回答
够拽才男人
2楼-- · 2019-01-03 14:14

If you still need to use Visual Studio 2013, you can actually write a loop, or lambda expression in the immediate window using also the package manager console window. In my case, I added a list at the top of the function:

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

Where my GetAll() function is:

private DbSet<T> _dbSet;

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

    return list;
}

Here I kept getting the following error, so I wanted to print out all the items in the various repositories:

InnerException {"The DELETE statement conflicted with the REFERENCE constraint \"FK_dbo.Department_dbo.RoleHierarchy_OranizationalRoleId\". The conflict occurred in database \"CC_Portal_SchoolObjectModel\", table \"dbo.Department\", column 'OranizationalRoleId'.\r\nThe statement has been terminated."} System.Exception {System.Data.SqlClient.SqlException}

Then, I find out how many records are in the department repository by executing this in the immediate window:

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

Which returned 243.

So, if you execute the following in the package manager console, it prints out all the items:

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

The author for the idea can be found here

查看更多
霸刀☆藐视天下
3楼-- · 2019-01-03 14:17

In VS 2015 you can do so now,this is one of the new feature they added.

查看更多
老娘就宠你
4楼-- · 2019-01-03 14:18

You can't use lambda expressions in the Immediate or Watch windows.

You can however use System.Linq.Dynamic expressions, which take the form .Where("Id = @0", 2) - it doesn't have the full range of methods available in standard Linq, and doesn't have the full power of lambda expressions, but still, it's better than nothing!

查看更多
女痞
5楼-- · 2019-01-03 14:25

The future has come!

Support for debugging lambda expressions has been added to Visual Studio 2015 (Preview at the time of writing).

Expression Evaluator had to be rewritten, so many features are missing: remote debugging ASP.NET, declaring variables in Immediate window, inspecting dynamic variables etc. Also lambda expressions that require calls to native functions aren't currently supported.

查看更多
老娘就宠你
6楼-- · 2019-01-03 14:27

this might help: Extended Immediate Window for Visual Studio (use Linq, Lambda Expr in Debugging)

All the best, Patrick

查看更多
家丑人穷心不美
7楼-- · 2019-01-03 14:29

No you cannot use lambda expressions in the watch / locals / immediate window. As Marc has pointed out this is incredibly complex. I wanted to dive a bit further into the topic though.

What most people don't consider with executing an anonymous function in the debugger is that it does not occur in a vaccuum. The very act of defining and running an anonymous function changes the underlying structure of the code base. Changing the code, in general, and in particular from the immediate window, is a very difficult task.

Consider the following code.

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

This particular code creates a single closure to capture the value v1. Closure capture is required whenever an anonymous function uses a variable declared outside it's scope. For all intents and purposes v1 no longer exists in this function. The last line actually looks more like the following

var v3 = closure1.v1 + v2;

If the function Example is run in the debugger it will stop at the Break line. Now imagine if the user typed the following into the watch window

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

In order to properly execute this the debugger (or more appropriate the EE) would need to create a closure for variable v2. This is difficult but not impossible to do.

What really makes this a tough job for the EE though is that last line. How should that line now be executed? For all intents and purposes the anonymous function deleted the v2 variable and replaced it with closure2.v2. So the last line of code really now needs to read

var v3 = closure1.v1 + closure2.v2;

Yet to actually get this effect in code requires the EE to change the last line of code which is actually an ENC action. While this specific example is possible, a good portion of the scenarios are not.

What's even worse is executing that lambda expression shouldn't be creating a new closure. It should actually be appending data to the original closure. At this point you run straight on into the limitations ENC.

My small example unfortunately only scratches the surface of the problems we run into. I keep saying I'll write a full blog post on this subject and hopefully I'll have time this weekend.

查看更多
登录 后发表回答