Debugging in IE 7 in Vista

I wrestled some in the past few days with with trying to debug some code that is hosted in Internet Explorer 7 under Vista.  I finally found the answer at http://blogs.msdn.com/webdevtools/archive/2006/09/18/761206.aspx, though they didn’t actually describe the same problem I saw.  (So here’s the description for future Googlers).

Short answer: Start Visual Studio via “Run as Administrator”.

Continue reading

DataTable.Load & ReadOnly Columns

Whew. I spent several hours over the past couple of days trying to find a nasty bug in some ADO.Net code. Updates would fail, and I discovered the problem was that, before I ever got to the point of trying to save the current row, it had already somehow gotten an error in it. The RowError had this text:

ReadOnly Data is Modified

If you’re reading this sometime shortly after 2006-06-30, try that phrase in Google, with quotes. Nadda. Apparently, no one had ever encountered that particular error and lived to tell about it.

Read on for more.
Continue reading

Anonymous Delegates: Are you sure you’ve captured what you think you have?

I ran across this issue a while back, and as I came across a need to exercise the knowledge gained again today, I thought I’d post a quick note for others.

What’s wrong with this code?


foreach (Form form in forms)
{
ToolStripItem item = new ToolStripMenuItem(
form.Text, CreateImage(form.Icon), delegate { Open(form); }
);
strip.Items.Add(item);
}

Hint for old Lisp hands: the delegate { } construct creates a closure.

The problem is that every item ends up opening the last form in the list when clicked.

Here’s why: the loop variable, form takes on a number of different values during the lifetime of the loop. When the compiler creates the closure for the anonymous delegate, it doesn’t capture the value of variables — it captures references to the variables themselves. In C# terms, it’s as if you had declared form as a ref parameter to the delegate.

To correct this problem, you have to do something like the following instead.


foreach (Form lf in forms)
{
Form form = lf; // Create a local var for the closure below.
ToolStripItem item = new ToolStripMenuItem(
form.Text, CreateImage(form.Icon), delegate { Open(form); }
);
strip.Items.Add(item);
}

Here, we created a new variable that is local to the scope within which the anonymous delegate is created, and we reference it instead of the loop variable. Unlike the loop variable, this new variable only ever has one value (per time that its scope is entered, which is what is important). I.e., even though the loop body may execute many times, the compiler is essentially creating a new variable (== a new storage location) for each loop execution. (In reality, the compiler is actually creating a new instance of an anonymous class to hold that variable each time the loop body executes).

If the above discussion sounds worrying from a performance standpoint, don’t get too worked up about it. You only pay the price of features like anonymous delegates if you actually use them; if that method had been written without the delegate { } construct, the compiler would have emitted code that uses the same memory location for each loop iteration, no hidden anonymous classes or other shenanigans involved. And even in cases where you do use anonymous delegates, the alternative is generally to manually do what the compiler would do for you: create a class to hold state and pass it around. Just being aware of what the code that you write actually means will help you avoid major performance snafus. In the case above, the cost of the anonymous delegate is negligible, b/c the maximum execution count for that loop is still very small — commonly between 5 and 10, and always less than about 20. For numbers that small, worrying about performance is just wasted time.

DLinq in C# 2.0

Out of curiosity, I decided to see what it would take to get DLinq working in C# 2.0. DLinq is really designed for C# 3.0, but it seems that none of the changes between 2.0 and 3.0 require new framework support — they’re all compiler-level. So, if you reference a DLL compiled with C# 3.0 (like System.Query, for instance) when compiling using the C# 2.0 compiler, things will work, minus the syntax enhancements to support it all.

It was a little harder than I’d thought. The only way I could figure out to get an initial Query object was to use reflection. Creating an initial Query (to which additional standard query operators may then be applied) is essentially equivalent to applying the from operator in C# 3.0. There is likely a better way, but even the better way may still rely on reflection: the LINQ docs describe how all of the new standard query operators are mapped to method calls except for from, for which I couldn’t find any information…

One gotcha: you have to use the exact same ParameterExpression object both to specify parameters to a lambda and to refer to that parameter within the lambda’s expression. Different objects that have the same name cause an “item not in dictionary” exception. (Example in code below is the widgetParm).

(Click “more” to see the code):
Continue reading

C# 2.0 Rocks

I’ve been playing with C# 2.0 for more than a year now, but now that I’m really using it in anger, I keep being surprised by just how helpful closures (anonymous delegates) are. The following used to require no fewer than six methods and about 4 times the number of lines of code.

private void OnClickZoomBn(object sender, EventArgs args)
{
            ContextMenuStrip menu = new ContextMenuStrip();
            menu.Items.Add("20%", null, delegate { m_printPreviewCtl.Zoom = 0.20; });
            menu.Items.Add("50%", null, delegate { m_printPreviewCtl.Zoom = 0.50; });
            menu.Items.Add("100%", null, delegate { m_printPreviewCtl.Zoom = 1.00; });
            menu.Items.Add("200%", null, delegate { m_printPreviewCtl.Zoom = 2.00; });
            menu.Items.Add("Auto", null, delegate { m_printPreviewCtl.AutoZoom = true; });
            menu.Show(m_zoomBn, new Point(2, 2));
}