Why is it not possible to evaluate lambdas in the immediate window? - c#

Is there any particular reason? Is it not possible at all or is it just not implemented yet? Maybe there are any third-party addins that allow lambda evaluations?
UPDATE:
I've found this project on codeplex Extended Immediate Window. Seems that it has been abandoned for some time, but this can be a proof of a concept. Does anybody know any other immediate window extension addins? The ones that can run for/foreach statements in C# for instance?

JaredPar of Microsoft wrote a couple of blog posts answering your question: part 1 and part 2. You'll find the answers there.

When writing a lambda, the act of capturing variables significantly alters the construction of the underlying code (moving variables into fields of compiler-generated classes, that could very easily themselves be chained closure-contexts).
Not even considering the general complexity of doing this, it would then have two choices:
capture all the variable values as constants; feasible and pretty simple, but could easily mean that the result of executing in the immediate window is very different to the result of executing in the main body (very undesirable)
rewrite the entire code (for the reasons outlined above) on the fly (at a guess, impossible)
Given a choice between "undesirable" and "impossible", I guess they simply chose not to implement a feature that would be inherently brittle, and very complex to write.

Well, I think it's because the immediate window can only evaluate expressions, or rather it can only do invocations and assignments. To evaluate a Lambda expression a closure would have to be created for that lambda, typchecked and then executed.
I think it comes down to that the Immediate window is just an evaluator and not an interpreter.
http://msdn.microsoft.com/en-us/library/f177hahy(VS.80).aspx
"The Immediate window is used at design time to debug and evaluate expressions, execute statements, print variable values, and so forth. It allows you to enter expressions to be evaluated or executed by the development language during debugging."
So in effect, your question boils down to why you can't define functions in the immediate window (since lambdas are just annonymous functions), and the answer I think is that it simply wasn't designed for that.

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: http://ogresoft.blogspot.ca/2013/06/how-to-write-loop-or-lambda-expression.html

I assume, that because it is lazy evaluation, the immediate window cannot know beforehand what values, the captured variables (closure), should have.

Related

Checking if atleasst one element in a list of a particular column has a value [duplicate]

Why can't I use lambda expressions while debugging in “Quick watch” window?
UPD: see also
Link
Link
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.
Lambda expressions, like anonymous methods, are actually very complex beasts. Even if we rule out Expression (.NET 3.5), that still leaves a lot of complexity, not least being captured variables, which fundamentally re-structure the code that uses them (what you think of as variables become fields on compiler-generated classes), with a bit of smoke and mirrors.
As such, I'm not in the least surprised that you can't use them idly - there is a lot of compiler work (and type generation behind the scenes) that supports this magic.
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!
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.
this might help:
Extended Immediate Window for Visual Studio (use Linq, Lambda Expr in Debugging)
http://extendedimmediatewin.codeplex.com/
http://dvuyka.spaces.live.com/blog/cns!305B02907E9BE19A!381.entry
All the best,
Patrick
Lambda expressions are not supported by the debugger's expression evaluator... which is hardly surprising since at compile time they are used to create methods (or Expression Trees) rather than expressions (take a look in Reflector with the display switched to .NET 2 to see them).
Plus of course they could form a closure, another whole layer of structure.
In VS 2015 you can do so now,this is one of the new feature they added.
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
To answer your question, here's the Visual Studio Program Manager's official explanation of why you can't do this. In short, because "it's really, really hard" to implement in VS. But the feature is currently in progress (as updated on Aug 2014).
Allow the evaluation of lambda expressions while debugging
Add your vote while you're there!

Running multiple lines on the immediate window in Visual Studio with C#

Is there a way to run multiple commands in a single entry in the immediate window of Visual Studio? I am running Visual Studio 2013.
I have a problem that is much easier to debug when I can create an input object within the immediate window and step through, but every time I make a change to the code I have to recreate the object like this:
var inputObject = new InputObject();
inputObject.Property1 = "value";
inputObject.Property2 = "value";
inputObject.Property3 = "value";
//etc.
It's a pain to have to rebuild this object by running each line individually to help debug this problem I have. Is there a way to run them all in one command? Something like this (though obviously this does not work):
var inputObject = new InputObject(); inputObject.Property1 = "value"; inputObject.Property2 = "value"; inputObject.Property3 = "value";
I do see that it is possible in Visual Basic from this link: Using colons to put two statements on the same line in Visual Basic
Any suggestions for other approaches to achieve the end goal are also welcome.
In short, no. I don't believe the Immediate Window supports multiple statements at this time.
edit -- #Christopher_G_Lewis is actually correct, you can declare and instantiate new variables, but I found that the statement must be terminated with a semi-colon, unlike many other expressions that may be evaluated without one.
What you are doing comes across as a difficult method of debugging. If you have an issue that is difficult to debug without conventional methods (e.g. stepping through code, breakpoints, tracing) you should consider a Debugging Aid.
Debugging aids can vary, but why not just actually compile in that small snippet of code temporarily to help you troubleshoot the problem? The Immediate Window in Visual Studio isn't really intended to create control flow or new objects on demand, but is more designed for executing simple statements and expressions for quick analysis.
Your example is a bit vague to recommend a specific approach though, and I'm unsure what you are actually trying to accomplish. A simple struct in your code would still allow you to use it via the Immediate Window, and if you are concerned about accidentally leaving it in code you can use a #DEBUG constant to ensure it doesn't get compiled into your release configurations.
#if DEBUG
struct DebuggingAid
{
public string A;
public string B;
public string C;
}
#endif
#if DEBUG
public void f()
{
var aid = new DebuggingAid { A = "TestValue1", B = "TestValue2" };
// var real data
MethodBeingDebuggedWithStubDebuggingAidData(aid.A, A.B);
}
#endif
I would definitely consider different debugging methods that are available to you though.
Breakpoints are more powerful than you might realize. You can set conditional statements and also print out information when a breakpoint is hit and even call functions.
Function Breakpoints allow you break on a method of a particular name in the event you can't track down when it might be called, or where it is called from. You can also set conditions and actions.
Tracing with System.Diagnostics.Debug and System.Diagnostics.Trace to assist in debugger output in the IDE, you can also write traces to files.
Debugging aids, as already shown, and remove them from your code when you're done, or leave them in but compiled out #if DEBUG.
Unit testing - There is no wrong time to add a unit test to your code base. You will need to refactor your code slightly to facilitate testability, such as passing in dependencies, which it may appear that is what you are trying to do? (stubbing in test values to something?).
Immediate Window, by just manipulating the real data you are trying to (stub?) rather than creating debugging aids or test objects
If you could provide a little more detail about what you are trying to accomplish it will be a bit easier to provide some guidance, but hopefully this has helped you.
Actually its pretty simple to initiate an object in the immediate window:
inputObject = new InputObject()
{TestMVC.Areas.UI.Controllers.ServersController.InputObject}
Property1: null
Property2: null
Property3: null
inputObject = new InputObject() {Property1 = "1", Property2 ="2", Property3 = "3"}
{TestMVC.Areas.UI.Controllers.ServersController.InputObject}
Property1: "1"
Property2: "2"
Property3: "3"
But this is still a single command. Multiple commands are not supported.
If these were just props of the same class I'd go like ChristopherGLewis's answer
You can run multiple disparate assignments (i.e. setting props in different classes, or assigning unrelated variables) by stuffing them into an array all on the same line; don't forget that assignments in c# return values...
new object[]{ some.Prop1 = "hello", other.Prop2 = "goodbye", third.Prop3 = GetSomeValue(), myArray[0] = 2, _timeNow = DateTime.Now }
You get an object array back (and immed dumps it to the window), but as part of creating the array, immed ran the statements..
some.Prop1 = "hello";
other.Prop3 = "goodbye";
third.Prop3 = GetSomeValue();
myArray[0] = 2;
_timeNow = DateTime.Now;
..captured their return values, and put them in the array. As a side effect of each evaluation, the assignments you wanted made, were done - you probably don't care about the return values
I don't know of a way to do this with voids (i.e. I don't know how to make the immed window run 2 void methods on a single line); everything I've tried responds with calls into native method Microsoft.Win32.Win32Native.GetStdHandle(int). Evaluation of native methods in this context is not supported
//doesn't work
new [] {(Action)(() => { Console.WriteLine("a"); Console.WriteLine("b"); })}.ToList().ForEach(x => x())
Actually it does work, probably because I am writing this answer 5 years after this question was written.
You see below I have declared a local var in the Immediate window then pressed Enter and used it in a later line in the Immediate window. I am using Visual Studio v.16.11.6

What does baking a method means?

I was reading this post here on micro ORM used on SO.
The author showed this stack-trace:
System.Reflection.Emit.DynamicMethod.CreateDelegate
System.Data.Linq.SqlClient.ObjectReaderCompiler.Compile
System.Data.Linq.SqlClient.SqlProvider.GetReaderFactory
System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Compile
System.Data.Linq.CommonDataServices+DeferredSourceFactory`1.ExecuteKeyQuery
System.Data.Linq.CommonDataServices+DeferredSourceFactory`1.Execute
System.Linq.Enumerable.SingleOrDefault
System.Data.Linq.EntityRef`1.get_Entity
Then said:
In the trace above you can see that 'EntityRef' is baking a method, which is not a problem, unless it is happening 100s of times a second.
Could someone explain the stack-trace in relation to what he meant by "baking a method" and why it would be a performance problem?
When you do something like:
int[] items = whatever;
IEnumerable<int> query = from item in items where item % 2 == 0 select item;
then the compiler turns that into something like:
static bool Predicate(int item) { return item % 2 == 0; }
...
IEnumerable<int> query = Enumerable.Where<int>(items, new Func<int, bool> (Predicate));
That is, the compiler generates the IL for the method. When you build the query object at runtime, the object returned by Where holds on to a delegate to the predicate, and executes the predicate when necessary.
But it is possible to build the IL for the delegate at runtime if you want to. What you do is persist the body of the predicate as an expression tree. At runtime the expression tree can dynamically compile itself into brand-new IL; basically we start up a very simplified compiler that knows how to generate IL for expression trees. That way you can change the details of the predicate at runtime and recompile the predicate without having to recompile the whole program.
The author of that comment is using "baking" as a slang for "dynamic lightweight code generation".
It refers to creating a method dynamically at run time, for example by using an expression tree. Compiling the expression tree to a method and returning a delegate for the compiled method could be called "baking" the method.
It's a fancy way of saying that they're emitting dynamic code using Refrection.Emit. A notoriously slow process.

IEnumerable vs IList and weird CrossThreadMessagingException during debugging

The initial code is this:
var processes = Process.GetProcesses().Where(p => p.MainWindowTitle.ToUpperInvariant().Contains("FOO"));
During debugging, if I try to call Count() on processes in the immediate window pane or inspect the "Results View" in the locals pane, I get a CrossThreadMessagingException. If I don't debug but just run the code, everything is fine. It is also fine if I convert the collection to a list before assigning it to processes and use the Count property during debugging.
What exactly is a CrossThreadMessagingException and why is the IEnumerable approach causing such an exception?
edit: Providing a bit more information about the exception.
Message: An exception 'Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException' occurred
Source: Microsoft.VisualStudio.Debugger.Runtime
StackTrace:
at Microsoft.VisualStudio.Debugger.Runtime.Main.ThrowCrossThreadMessageException(String formatString)
at Microsoft.Win32.NativeMethods.GetWindowTextLength(HandleRef hWnd)
at System.Diagnostics.Process.get_MainWindowTitle()
This might totally be wrong, but I gather it's a mixture of deferred enumeration with WhereArrayIterator, and the debugger attempting to enumerate it?
I get the feeling, where the immediate window is trying to enumerate your result, it is doing so on another thread (which is causing the CrossThreadMessagingException).
It's not doing it when you call ToList, because ToList causes the enumeration to run immediately and concatenate the results in the list. This is done before you attempt to use the Count method in the immediate window.
When you use Count() without the ToList call, it forces the WhereArrayIterator (which is the return value of your Where method call) to enumerate, which is then trying to access the your lamda delegate from another thread.
On testing, you can actually enumerate other instances of WhereArrayIterator through immediate, so I think this is your particular use case, where you are trying to enumerate over the Process type, which I think internally makes calls using the Win32 API.
Internally, the Process.MainWindowTitle property uses lazy loading for its value. It doesn't actually make the call to grab the information, until the property is accessed for the first time (and also, it does so without locking, so if there where multiple threads accessing that area of the code, it is not atomic, so there is an inherit risk of race conditions - It shouldn't matter to much anyway, as it is a read only property, who's value should always be the same).
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[MonitoringDescription("ProcessMainWindowTitle")]
public string MainWindowTitle
{
get
{
if (this.mainWindowTitle == null)
{
IntPtr mainWindowHandle = this.MainWindowHandle;
if (mainWindowHandle == (IntPtr) 0)
{
this.mainWindowTitle = string.Empty;
}
else
{
StringBuilder lpString = new StringBuilder(Microsoft.Win32.NativeMethods.GetWindowTextLength(new HandleRef((object) this, mainWindowHandle)) * 2);
Microsoft.Win32.NativeMethods.GetWindowText(new HandleRef((object) this, mainWindowHandle), lpString, lpString.Capacity);
this.mainWindowTitle = ((object) lpString).ToString();
}
}
return this.mainWindowTitle;
}
}
When it is first accessed, the property makes a Win32 call to grab the window text. I believe this is where it seems to be falling over. But it only seems to fall over when using deferred enumeration with your WhereArrayIterator instance.
This is all a blind guess to be honest!

Precompile Lambda Expression Tree conversions as constants?

It is fairly common to take an Expression tree, and convert it to some other form, such as a string representation (for example this question and this question, and I suspect Linq2Sql does something similar).
In many cases, perhaps even most cases, the Expression tree conversion will always be the same, i.e. if I have a function
public string GenerateSomeSql(Expression<Func<TResult, TProperty>> expression)
then any call with the same argument will always return the same result for example:
GenerateSomeSql(x => x.Age) //suppose this will always return "select Age from Person"
GenerateSomeSql(x => x.Ssn) //suppose this will always return "select Ssn from Person"
So, in essence, the function call with a particular argument is really just a constant, except time is wasted at runtime re-computing it continuously.
Assuming, for the sake of argument, that the conversion was sufficiently complex to cause a noticeable performance hit, is there any way to pre-compile the function call into an actual constant?
Edit
It appears that there is no way to do this exactly within C# itself. The closest you can probably come within c# is the accepted answer (though of course you would want to make sure that the caching itself wasn't slower than regenerating). To actually convert to true constants, I suspect that with some work, you could use something like mono-cecil to modify the bytecodes after compilation.
The excellent LINQ IQueryable Toolkit project has a query cache that does something similar to what you've described. It contains an ExpressionComparer class that walks the hierarchy of two expressions and determines if they are equivalent. This technique is also used to collect references to common properties for parameterization and in the removal of redundant joins.
All you would need to do is come up with an expression hashing strategy so you can store the results of your processed expressions in a dictionary, ready for future reuse.
Your method would then look something like this:
private readonly IDictionary<Expression, string> _cache
= new Dictionary<Expression, string>(new ExpressionEqualityComparer());
public string GenerateSomeSql(Expression<Func<TResult, TProperty>> expression)
{
string sql;
if (!_cache.TryGetValue(expression, out sql))
{
//process expression
_cache.Add(expression, sql);
}
return sql;
}
class ExpressionEqualityComparer : IEqualityComparer<Expression>
{
public bool Equals(Expression x, Expression y)
{
return ExpressionComparer.AreEqual(x, y);
}
public int GetHashCode(Expression obj)
{
return ExpressionHasher.GetHash(obj);
}
}
First of all, I suspect that your assumption about compiling an expression causing a performance hit will not actually pan out in reality. My experience shows that there are many more factors (database access, network latency, very poor algorithms) that cause performance bottlenecks before regular "good" code causes issues. Premature optimization is the root of all evil, so build your application and run stress tests to find the actual performance bottlenecks, as they are often not where you would expect.
With that said, I think that pre-compilation depends on what the Expression is being tranlated into. I know that with LINQ to SQL you can call DataContext.GetCommand(Expression) and retrieve a DBCommand, which you could then cache and reuse.

Categories

Resources