<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Mike Stall's .NET Debugging Blog</title><subtitle type="html">Notes on Managed Debugging, ICorDebug, and random .NET stuff</subtitle><id>http://blogs.msdn.com/jmstall/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/jmstall/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2008-03-17T09:00:50Z</updated><entry><title>Speaking at Lake County .NET User’s Group</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2009/09/09/speaking-at-lake-county-net-user-s-group.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2009/09/09/speaking-at-lake-county-net-user-s-group.aspx</id><published>2009-09-09T22:16:00Z</published><updated>2009-09-09T22:16:00Z</updated><content type="html">&lt;p&gt;I’ll be &lt;a href="http://www.lcnug.org/events/09-09-08/LCNUG_September_24_C_4_0-4248649912.aspx" target="_blank"&gt;speaking&lt;/a&gt; at the &lt;a href="http://www.lcnug.org/Home.aspx" target="_blank"&gt;Lake County .NET User’s Group&lt;/a&gt; (LCNUG) near Chicago, Illinois on September 24th.&amp;#160; I’ll be talking about new features in C# 4.0, including named and optional parameters, dynamic support, scripting, office interop and No-PIA (Primary-Interop-Assemblies) support.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;The permalink for the event is &lt;a href="http://www.lcnug.org/events/09-09-08/LCNUG_September_24_C_4_0-4248649912.aspx" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;If you’re in the area, swing on by! &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9892937" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author></entry><entry><title>Writing a CLR Debugger in Python</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2009/09/08/writing-a-clr-debugger-in-python.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2009/09/08/writing-a-clr-debugger-in-python.aspx</id><published>2009-09-09T06:13:19Z</published><updated>2009-09-09T06:13:19Z</updated><content type="html">&lt;p&gt;&lt;a href="http://devhawk.net"&gt;Harry Pierson&lt;/a&gt; has written an excellent set of blog entries about writing a managed debugger in &lt;a href="http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython"&gt;IronPython&lt;/a&gt;. He builds on the ICorDebug managed wrappers that we ship in &lt;a href="http://blogs.msdn.com/jmstall/archive/2005/11/08/mdbg_linkfest.aspx"&gt;Mdbg&lt;/a&gt; and explains many of the concepts for how to write a debugger, such as managing breakpoints.&amp;#160; &lt;/p&gt;  &lt;p&gt;Read more about them &lt;a href="http://devhawk.net/CategoryView,category,Debugger.aspx"&gt;here&lt;/a&gt;.&amp;#160; &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9892924" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author><category term="MDbg" scheme="http://blogs.msdn.com/jmstall/archive/tags/MDbg/default.aspx" /></entry><entry><title>ICustomQueryInterface and CLR V4</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2009/07/09/icustomqueryinterface-and-clr-v4.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2009/07/09/icustomqueryinterface-and-clr-v4.aspx</id><published>2009-07-10T03:02:25Z</published><updated>2009-07-10T03:02:25Z</updated><content type="html">&lt;p&gt;CLR V4 fixes an issue with COM-interop that’s been bothering me for a while. The problem is that unless you’re using a PIA, &lt;em&gt;you can often have either your caller &lt;u&gt;or&lt;/u&gt; callee be managed code, but not both&lt;/em&gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;You can import the same COM-classic interface into managed code multiple times, and two components can naturally end up with two different .NET types representing the same single COM-classic interface. Furthermore, the types can be imported with different managed signatures because of things like [PreserveSig] attributes and different ways to marshal data types.&lt;/p&gt;  &lt;p&gt;(PIAs are supposed to alleviate that by providing a single unified definition, but then getting multiple components to agree on that unified definition is its own problem. CLR V4 added support for to avoid requiring PIAs. see &lt;a href="http://blogs.msdn.com/mshneer/archive/2008/10/28/better-eventing-support-in-clr-4-0-using-nopia-support.aspx"&gt;NoPia&lt;/a&gt;. )&lt;/p&gt;  &lt;p&gt;When managed code calls a COM interface that is implemented by managed code (Managed –&amp;gt; Native –&amp;gt; Managed), the CLR detects that the COM-object is really a managed implementation and creates a direct managed call (Managed –&amp;gt; Managed). So if your caller and callee are bound to different .NET types for the interface, the CLR won’t realize it’s a COM-interface call and will just fail on the .NET type mismatch.&lt;/p&gt;  &lt;p&gt;CLR V4 fixes this by adding the &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.icustomqueryinterface.getinterface(VS.100).aspx"&gt;ICustomQueryInterface&lt;/a&gt; that lets a managed object really act as if it’s native code when being called through COM-interop.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Where I hit this…&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I hit this as I was writing debugger code in Managed. We had a managed application (&lt;a href="http://blogs.msdn.com/jmstall/archive/2005/11/08/mdbg_linkfest.aspx"&gt;MDbg&lt;/a&gt;) that used COM-interop to call into a native implementation of ICorDebug. That worked great (managed calling native). Later, we had some cases of creating a managed implementation of certain ICorDebug interfaces. But that failed from Mdbg because they had different COM-interop import definitions for ICorDebug. &lt;/p&gt;  &lt;p&gt;This also just naturally starts showing up as people are porting more and more of their legacy systems to managed code. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Code sample demonstrating the problem&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Say you have a COM-classic interface IFoo, imported by 2 different components:&lt;/p&gt;  &lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;ComImport&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;InterfaceType&lt;/span&gt;(1), &lt;span style="color: #2b91af"&gt;ComConversionLoss&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;Guid&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;FC3E287D-D659-4E1D-81D5-9D29398C7237&amp;quot;&lt;/span&gt;)]
&lt;span style="color: blue"&gt;interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IFoo1
&lt;/span&gt;{
    [&lt;span style="color: #2b91af"&gt;PreserveSig&lt;/span&gt;]
    &lt;span style="color: blue"&gt;int &lt;/span&gt;Thing(&lt;span style="color: blue"&gt;int &lt;/span&gt;x);
}

[&lt;span style="color: #2b91af"&gt;ComImport&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;InterfaceType&lt;/span&gt;(1), &lt;span style="color: #2b91af"&gt;ComConversionLoss&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;Guid&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;FC3E287D-D659-4E1D-81D5-9D29398C7237&amp;quot;&lt;/span&gt;)]
&lt;span style="color: blue"&gt;interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IFoo2
&lt;/span&gt;{        
    &lt;span style="color: blue"&gt;void &lt;/span&gt;Thing(&lt;span style="color: blue"&gt;int &lt;/span&gt;x);
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Now suppose you have a class C1 that implements IFoo1. IFoo1 and IFoo2 represent the same COM interface and have the same GUID, so you’d like to be able to use them interchangeably. However, they’re 2 different .NET types. typeof(IFoo1) != typeof(IFoo2).&lt;/p&gt;

&lt;p&gt;Ideally, you’d like the following snippet to succeed and call Thing(5) and Thing(3) on the object instance obj.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;static void &lt;/span&gt;Main(&lt;span style="color: blue"&gt;string&lt;/span&gt;[] args)
{
    &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Hi!&amp;quot;&lt;/span&gt;);

    &lt;span style="color: blue"&gt;object &lt;/span&gt;obj = &lt;span style="color: blue"&gt;new &lt;/span&gt;C1();
    obj = GetRCW(obj); // get a COM object for C1

    IFoo1 f1 = (IFoo1)obj;
    IFoo2 f2 = (IFoo2)obj; // Fails!!! obj is really a C1, and can’t cast to a IFoo2
    f1.Thing(5);
    f2.Thing(3);
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Run that and you get an invalid cast exception because it can’t cast C1 to a IFoo2. It doesn’t understand that IFoo2 and IFoo1 are the same interface..&lt;/p&gt;

&lt;table border="1"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
        &lt;pre&gt;&lt;b&gt;&lt;span style="color: rgb(0,0,160)"&gt;C:\TEMP&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: rgb(164,0,0)"&gt;b.exe&lt;/span&gt;&lt;/i&gt;
Hi!

Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'ConsoleApplication4.C1' to type 'ConsoleApplication4.IFoo2'.
   at ConsoleApplication4.Program.Main(String[] args)&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ICustomQueryInterface to the rescue. &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CLR 4 allows an object to hook ICustomQueryInterface and have fine grain control over QI calls. The CLR detects that C1 is really a managed object because of a QI for a secret interface, &lt;a href="http://msdn.microsoft.com/en-us/library/ms404390.aspx"&gt;IManagedObject&lt;/a&gt;. C1 can intercept this QI call and fail it (by returning CustomQueryInterfaceResult.Failed), and thus look like a native object.&amp;#160; It passes all other QI calls through to the RCW’s QI handling (via returning CustomQueryInterfaceResult.NotHandled)&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System;
&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Collections.Generic;
&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Linq;
&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Text;
&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Runtime.InteropServices;

&lt;span style="color: blue"&gt;namespace &lt;/span&gt;ConsoleApplication4
{
    [&lt;span style="color: #2b91af"&gt;ComImport&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;InterfaceType&lt;/span&gt;(1), &lt;span style="color: #2b91af"&gt;ComConversionLoss&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;Guid&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;FC3E287D-D659-4E1D-81D5-9D29398C7237&amp;quot;&lt;/span&gt;)]
    &lt;span style="color: blue"&gt;interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IFoo1
    &lt;/span&gt;{
        [&lt;span style="color: #2b91af"&gt;PreserveSig&lt;/span&gt;]
        &lt;span style="color: blue"&gt;int &lt;/span&gt;Thing(&lt;span style="color: blue"&gt;int &lt;/span&gt;x);
    }

    [&lt;span style="color: #2b91af"&gt;ComImport&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;InterfaceType&lt;/span&gt;(1), &lt;span style="color: #2b91af"&gt;ComConversionLoss&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;Guid&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;FC3E287D-D659-4E1D-81D5-9D29398C7237&amp;quot;&lt;/span&gt;)]
    &lt;span style="color: blue"&gt;interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IFoo2
    &lt;/span&gt;{        
        &lt;span style="color: blue"&gt;void &lt;/span&gt;Thing(&lt;span style="color: blue"&gt;int &lt;/span&gt;x);
    }


    &lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;C1 &lt;/span&gt;: IFoo1, ICustomQueryInterface
    {

        &lt;span style="color: blue"&gt;static readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Guid &lt;/span&gt;IID_IMarshal = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Guid&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;00000003-0000-0000-C000-000000000046&amp;quot;&lt;/span&gt;);
        &lt;span style="color: blue"&gt;static readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Guid &lt;/span&gt;IID_IManagedObject = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Guid&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;C3FCC19E-A970-11d2-8B5A-00A0C9B7C9C4&amp;quot;&lt;/span&gt;);

        CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(&lt;span style="color: blue"&gt;ref &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Guid &lt;/span&gt;iid, &lt;span style="color: blue"&gt;out &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IntPtr &lt;/span&gt;ppv)
        {
            &lt;span style="color: blue"&gt;if &lt;/span&gt;(iid == IID_IMarshal ||
                iid == IID_IManagedObject
                )
            {
                ppv = &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt;.Zero;
                &lt;span style="color: blue"&gt;return &lt;/span&gt;CustomQueryInterfaceResult.Failed;
            }

            ppv = &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt;.Zero;
            &lt;span style="color: blue"&gt;return &lt;/span&gt;CustomQueryInterfaceResult.NotHandled;
        }



        &lt;span style="color: blue"&gt;#region &lt;/span&gt;IFoo1 Members

        &lt;span style="color: blue"&gt;public int &lt;/span&gt;Thing(&lt;span style="color: blue"&gt;int &lt;/span&gt;x)
        {
            &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Inside C1={0}&amp;quot;&lt;/span&gt;, x);
            &lt;span style="color: blue"&gt;return &lt;/span&gt;0;
        }

        &lt;span style="color: blue"&gt;#endregion
    &lt;/span&gt;}


   
    &lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Program
    &lt;/span&gt;{
        &lt;span style="color: green"&gt;// Convert it to a RCW
        &lt;/span&gt;&lt;span style="color: blue"&gt;static object &lt;/span&gt;GetRCW(&lt;span style="color: blue"&gt;object &lt;/span&gt;o)
        {
            &lt;span style="color: #2b91af"&gt;IntPtr &lt;/span&gt;ip = &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt;.Zero;
            &lt;span style="color: blue"&gt;try
            &lt;/span&gt;{
                ip = &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.GetIUnknownForObject(o);
                &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.GetObjectForIUnknown(ip);
            }
            &lt;span style="color: blue"&gt;finally
            &lt;/span&gt;{
                &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.Release(ip);
            }
        }

        &lt;span style="color: blue"&gt;static void &lt;/span&gt;Main(&lt;span style="color: blue"&gt;string&lt;/span&gt;[] args)
        {
            &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Hi!&amp;quot;&lt;/span&gt;);

            &lt;span style="color: blue"&gt;object &lt;/span&gt;c1 = &lt;span style="color: blue"&gt;new &lt;/span&gt;C1();
            &lt;span style="color: blue"&gt;object &lt;/span&gt;obj = GetRCW(c1);

            &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(c1.GetType().FullName); &lt;span style="color: green"&gt;// ConsoleApplication4.C1
            &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(obj.GetType().FullName); &lt;span style="color: green"&gt;// System.__ComObject

            &lt;/span&gt;IFoo1 f1 = (IFoo1)obj;
            IFoo2 f2 = (IFoo2)obj;
            f1.Thing(5);
            f2.Thing(3);
        }
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;We call GetRCW() to convert the object to a Runtime Callable Wrapper (RCW) so that the CLR will actually do COM-interop dispatch. You can observe the GetType() calls on c1 vs. obj.&lt;/p&gt;

&lt;p&gt;Notice now both calls via Thing(5) and Thing(3) succeed. And they’re even going through different import signatures.&lt;/p&gt;

&lt;table border="1"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
        &lt;pre&gt;&lt;b&gt;&lt;span style="color: rgb(0,0,160)"&gt;C:\TEMP&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: rgb(164,0,0)"&gt;a.exe&lt;/span&gt;&lt;/i&gt;
Hi!
ConsoleApplication4.C1
System.__ComObject
Inside C1=5
Inside C1=3&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Thanks to Paul Harrington (a dev on the Visual Studio Platform team) and Misha Shneerson&amp;#160; for pointing me at the new functionality and code snippet for C1.GetInterface()&amp;#160; Misha has a lot more information about CLR V4 COM-interop advances on his blog at &lt;a title="http://blogs.msdn.com/mshneer/" href="http://blogs.msdn.com/mshneer/"&gt;http://blogs.msdn.com/mshneer/&lt;/a&gt;.&lt;/p&gt;

&lt;pre class="code"&gt;&amp;#160;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9827872" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author></entry><entry><title>Virtual code execution via IL interpretation</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2009/05/21/virtual-code-execution-via-il-interpretation.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2009/05/21/virtual-code-execution-via-il-interpretation.aspx</id><published>2009-05-22T03:10:32Z</published><updated>2009-05-22T03:10:32Z</updated><content type="html">&lt;p&gt;As Soma announced, &lt;a href="http://blogs.msdn.com/somasegar/archive/2009/05/18/visual-studio-2010-and-net-fx-4-beta-1-ships.aspx"&gt;we just shipped VS2010 Beta1&lt;/a&gt;. This includes &lt;a href="http://blogs.msdn.com/rmbyers/archive/2008/10/30/clr-4-0-advancements-in-diagnostics.aspx"&gt;dump debugging support for managed code&lt;/a&gt; and a very cool bonus feature tucked in there that I’ll blog about today. &lt;/p&gt; &lt;p&gt;Dump-debugging (aka post-mortem debugging) is very useful and a long-requested feature for managed code.&amp;nbsp; The downside is that with a dump-file, you don’t have a live process anymore, and so &lt;a href="http://blogs.msdn.com/jmstall/archive/tags/FuncEval/default.aspx"&gt;property-evaluation&lt;/a&gt; won’t work. That’s because property evaluation is implemented by hijacking a thread in the debuggee to run the function of interest, commonly a ToString() or property-getter. There’s no live thread to hijack in post-mortem debugging.&lt;/p&gt; &lt;p&gt;We have a mitigation for that in VS2010. In addition to loading the dump file, &lt;strong&gt;we can also interpret the IL opcodes of the function and simulate execution &lt;/strong&gt;to show the results in the debugger.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Here, I’ll just blog about the end-user experience and some top-level points. I’ll save the technical drill down for future blogs.&lt;/p&gt; &lt;p&gt;Consider the following sample:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System;
&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Collections.Generic;
&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Linq;
&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Text;
&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Reflection;

&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Point 
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;int &lt;/span&gt;m_x;
    &lt;span style="color: blue"&gt;int &lt;/span&gt;m_y;
    &lt;span style="color: blue"&gt;public &lt;/span&gt;Point(&lt;span style="color: blue"&gt;int &lt;/span&gt;x, &lt;span style="color: blue"&gt;int &lt;/span&gt;y)
    {
        m_x = x;
        m_y = y;
    }
    &lt;span style="color: blue"&gt;public override string &lt;/span&gt;ToString()
    {
        &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;"({0},{1})"&lt;/span&gt;, &lt;span style="color: blue"&gt;this&lt;/span&gt;.X, &lt;span style="color: blue"&gt;this&lt;/span&gt;.Y);
    }

    &lt;span style="color: blue"&gt;public int &lt;/span&gt;X
    {
        &lt;span style="color: blue"&gt;get
        &lt;/span&gt;{
            &lt;span style="color: blue"&gt;return &lt;/span&gt;m_x;
        }
    }
    &lt;span style="color: blue"&gt;public int &lt;/span&gt;Y
    {
        &lt;span style="color: blue"&gt;get
        &lt;/span&gt;{
            &lt;span style="color: blue"&gt;return &lt;/span&gt;m_y;
        }
    }
}

&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Program
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;static void &lt;/span&gt;Main(&lt;span style="color: blue"&gt;string&lt;/span&gt;[] args)
    {
        &lt;span style="color: #2b91af"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt; dict = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt;();
        dict[5] = &lt;span style="color: #a31515"&gt;"Five"&lt;/span&gt;;
        dict[3] = &lt;span style="color: #a31515"&gt;"three"&lt;/span&gt;;

        &lt;span style="color: #2b91af"&gt;Point &lt;/span&gt;p = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Point&lt;/span&gt;(3, 4);
                
    }

    &lt;span style="color: blue"&gt;public static int  &lt;/span&gt;Dot(&lt;span style="color: #2b91af"&gt;Point &lt;/span&gt;p1, &lt;span style="color: #2b91af"&gt;Point &lt;/span&gt;p2)
    {
        &lt;span style="color: blue"&gt;int &lt;/span&gt;r2 = p1.X * p2.X + p1.Y * p2.Y;
        &lt;span style="color: blue"&gt;return &lt;/span&gt;r2;
    }

}

&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;&amp;nbsp;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Suppose you have a dump-file from a thread stopped at the end of Main() (See newly added menu item “Debug | Save Dump As …”; load dump-file via “File | Open | File …”).&lt;/p&gt;
&lt;p&gt;Normally, you could see the locals (dict, p) and their raw fields, but you wouldn’t be able to see the properties or ToString() values. So it would look something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/jmstall/WindowsLiveWriter/SafecodeexecutionviaanILinterpreter_99B5/image_6.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/jmstall/WindowsLiveWriter/SafecodeexecutionviaanILinterpreter_99B5/image_thumb_2.png" width="563" height="148"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;But with the interpreter, you can actually simulate execution. With the IL interpreter, here’s what it looks like in the watch window:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/jmstall/WindowsLiveWriter/SafecodeexecutionviaanILinterpreter_99B5/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/jmstall/WindowsLiveWriter/SafecodeexecutionviaanILinterpreter_99B5/image_thumb.png" width="409" height="181"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Which is exactly what you’d expect with live-debugging.&amp;nbsp; (In one sense, “everything still works like it worked before” is not a gratifying demo…)&lt;/p&gt;
&lt;p&gt;The ‘*’ after the values are indications that they came from the interpreter.&amp;nbsp; Note you still need to ensure that property-evaluation is enabled in “Tools | options | Debugging”:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/jmstall/WindowsLiveWriter/SafecodeexecutionviaanILinterpreter_99B5/image_8.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/jmstall/WindowsLiveWriter/SafecodeexecutionviaanILinterpreter_99B5/image_thumb_3.png" width="356" height="45"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How does it work?&lt;br&gt;&lt;/strong&gt;The Interpreter gets the raw IL opcodes via ICorDebug and then simulates execution of those opcodes. For example, when you inspect “p.X” in the watch window, the debugger can get the raw IL opcodes:&lt;/p&gt;
&lt;p&gt;.method public hidebysig specialname instance int32 &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get_X() cil managed&lt;br&gt;{&lt;br&gt;&amp;nbsp; // Code size&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 12 (0xc)&lt;br&gt;&amp;nbsp; .maxstack&amp;nbsp; 1&lt;br&gt;&amp;nbsp; .locals init ([0] int32 CS$1$0000)&lt;br&gt;&amp;nbsp; IL_0000:&amp;nbsp; nop&lt;br&gt;&amp;nbsp; IL_0001:&amp;nbsp; ldarg.0&lt;br&gt;&amp;nbsp; IL_0002:&amp;nbsp; &lt;strong&gt;ldfld&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int32 Point::m_x&lt;/strong&gt;&lt;br&gt;&amp;nbsp; IL_0007:&amp;nbsp; stloc.0&lt;br&gt;&amp;nbsp; IL_0008:&amp;nbsp; br.s&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IL_000a&lt;br&gt;&amp;nbsp; IL_000a:&amp;nbsp; ldloc.0&lt;br&gt;&amp;nbsp; IL_000b:&amp;nbsp; ret&lt;br&gt;} // end of method Point::get_X 
&lt;p&gt;And then translate that ldfld opcode into a ICorDebug field fetch the same way it would fetch “p.m_x”. The problem gets a lot harder then that (eg, how does it interpret a newobj instruction?) but that’s the basic idea.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Other things it can interpret&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;The immediate window is also wired up to use the interpreter when dump-debugging. Here are some sample things that work. Again, note the ‘*’ means the results are in the interpreter and the debuggee is not modified.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;Simulating new objects&lt;/u&gt;:&lt;br&gt;? new Point(10,12).ToString()&lt;br&gt;"(10,12)"*&lt;br&gt;&lt;br&gt;&lt;u&gt;Basic reflection&lt;/u&gt;:&lt;br&gt;? typeof(Point).FullName&lt;br&gt;"Point"*&lt;br&gt;&lt;br&gt;&lt;u&gt;Dynamic method invocation&lt;/u&gt;:&lt;br&gt;? typeof(Point).GetMethod("get_X").Invoke(new Point(6,7), null)&lt;br&gt;0x00000006*&lt;/p&gt;
&lt;p&gt;&lt;u&gt;Calling functions, and even mixing debuggee data (the local variable ‘p’) with interpreter generated data (via the ‘new’ expression)&lt;/u&gt;:&lt;br&gt;? Dot(p,new Point(10,20))&lt;br&gt;110*&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It even works for Visualizers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Notice that it can even load the Visualizer for the Dictionary (dict) and show you the contents as a pretty array view rather than just the raw view of buckets. Visualizers are their own dll,&amp;nbsp; and we can verify that the dll is not actually loaded into the debuggee. For example, the Dictionary visualizer dll is&amp;nbsp; Microsoft.VisualStudio.DebuggerVisualizers.dll, but that’s not in the module list:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/jmstall/WindowsLiveWriter/SafecodeexecutionviaanILinterpreter_99B5/image_4.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/jmstall/WindowsLiveWriter/SafecodeexecutionviaanILinterpreter_99B5/image_thumb_1.png" width="351" height="217"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;That’s because the interpreter has virtualized loading the visualizer dll into its own “virtual interpreter” space and not the actual debuggee process space. That’s important because in a dump file, you can’t load a visualizer dll post-mortem.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Other issues&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;There are lots of other details here that I’m skipping over, like: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The interpreter is definitely not bullet proof. If it sees something it can’t interpreter (like a pinvoke or dangerous code), then it simply aborts the interpretation attempt.&lt;/li&gt;
&lt;li&gt;The intepreter is recursive, so it can handle functions that call other functions. (Notice that ToString call get_X.)&lt;/li&gt;
&lt;li&gt;How does it deal with side-effecting operations? &lt;/li&gt;
&lt;li&gt;How does it handle virtual dispatch call opcodes?&lt;/li&gt;
&lt;li&gt;How does it handle ecalls?&lt;/li&gt;
&lt;li&gt;How does it handle reflection&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Other advantages&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;There are other advantages of IL interpretation for function evaluation, mainly that it addresses the ”&lt;a href="http://blogs.msdn.com/jmstall/archive/2005/03/23/400794.aspx"&gt;func-eval is evil&lt;/a&gt;” problems by essentially degenerating dangerous func-evals to safe field accesses.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It is provably safe because it errs on the side of safety. The interpreter is completely non-invasive (it operates on a dump-file!).&lt;/li&gt;
&lt;li&gt;No accidentally executing dangerous code. &lt;/li&gt;
&lt;li&gt;Side-effect free func-evals. This is a natural consequence of it being non-invasive.&lt;/li&gt;
&lt;li&gt;Bullet proof func-eval abort. &lt;/li&gt;
&lt;li&gt;Bullet proof protection against recursive properties that stack-overflow.&lt;/li&gt;
&lt;li&gt;It allows func-eval to occur at places &lt;a href="http://blogs.msdn.com/jmstall/archive/2005/11/15/funceval-rules.aspx"&gt;previously impossible&lt;/a&gt;, such as in dump-files, when the thread is in native code, retail code, or places where there is no thread to hijack.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Closing thoughts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We realize that the interpreter is definitely not perfect. That’s part of why we choose to have it active in dump-files but not replace func-eval in regular execution. For dump-file scenarios, it took something that would have been completely broken and made many things work.&amp;nbsp; &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9634517" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author><category term="ICorDebug" scheme="http://blogs.msdn.com/jmstall/archive/tags/ICorDebug/default.aspx" /><category term="FuncEval" scheme="http://blogs.msdn.com/jmstall/archive/tags/FuncEval/default.aspx" /></entry><entry><title>MVP Summit 2009</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2009/02/27/mvp-summit-2009.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2009/02/27/mvp-summit-2009.aspx</id><published>2009-02-27T22:45:56Z</published><updated>2009-02-27T22:45:56Z</updated><content type="html">&lt;p&gt;For those going to the &lt;a href="http://www.mvpsummit2009.com/public/technicaleducation.aspx "&gt;2009 MVP Summit&lt;/a&gt;, I’ll be one of the speakers at the breakout sessions on March 2nd on Microsoft’s Main campus.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9449473" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author></entry><entry><title>Managed Dump debugging support for Visual Studio and ICorDebug</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/11/01/managed-dump-debugging-support-for-visual-studio-and-icordebug.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/11/01/managed-dump-debugging-support-for-visual-studio-and-icordebug.aspx</id><published>2008-11-01T19:51:57Z</published><updated>2008-11-01T19:51:57Z</updated><content type="html">&lt;p&gt;This is the longest I've gone without blogging, but our &lt;a href="http://www.microsoftpdc.com/"&gt;PDC&lt;/a&gt; announcements have stuff way too cool to stay quiet about. &lt;/p&gt; &lt;p&gt;If you saw &lt;a href="http://www.microsoftpdc.com/"&gt;PDC&lt;/a&gt;, you've head that the CLR Debugging API, &lt;strong&gt;ICorDebug, will support dump-debugging&lt;/strong&gt;. This enables any ICorDebug-based debugger (including Visual Studio and MDbg) to debug dump-files of .NET applications. The coolness goes well beyond that, but dump-debugging is just the easiest feature to describe. &lt;/p&gt; &lt;p&gt;This was not an overnight feature, and required some major architectural changes to be plumbed through the entire system.&amp;nbsp; Specifically, when dump-debugging, there's no 'live' debuggee, so you can't rely on a &lt;a href="http://blogs.msdn.com/jmstall/archive/2004/10/13/241828.aspx"&gt;helper-thread&lt;/a&gt; running in the debuggee process to service debugging requests anymore, so you need a completely different model. &lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/rmbyers/"&gt;Rick Byers&lt;/a&gt; has an excellent description of the &lt;a href="http://blogs.msdn.com/rmbyers/archive/2008/10/27/icordebug-re-architecture-in-clr-4-0.aspx"&gt;ICorDebug re-architecture in CLR 4.0&lt;/a&gt;.&amp;nbsp; He also describes some of the &lt;a href="http://blogs.msdn.com/rmbyers/archive/2008/10/30/clr-4-0-advancements-in-diagnostics.aspx"&gt;other advancements in the CLR Tools API space&lt;/a&gt;. Go read them.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9028315" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author><category term="ICorDebug" scheme="http://blogs.msdn.com/jmstall/archive/tags/ICorDebug/default.aspx" /></entry><entry><title>Updated MSDN forums</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/06/10/updated-msdn-forums.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/06/10/updated-msdn-forums.aspx</id><published>2008-06-10T07:41:13Z</published><updated>2008-06-10T07:41:13Z</updated><content type="html">&lt;p&gt;The MSDN forums are updated and have a new look and feel. It's at a new link too:&amp;nbsp; &lt;a title="http://forums.msdn.microsoft.com/en-US/netfxtoolsdev/threads/" href="http://forums.msdn.microsoft.com/en-US/netfxtoolsdev/threads/"&gt;http://forums.msdn.microsoft.com/en-US/netfxtoolsdev/threads/&lt;/a&gt;&amp;nbsp; (the old link still forwards).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8588669" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author></entry><entry><title>Stuff in Reflection that's not in Metadata</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/05/23/stuff-in-reflection-that-s-not-in-metadata.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/05/23/stuff-in-reflection-that-s-not-in-metadata.aspx</id><published>2008-05-23T08:01:33Z</published><updated>2008-05-23T08:01:33Z</updated><content type="html">&lt;p&gt;Previously, I mentioned some things in &lt;a href="http://blogs.msdn.com/jmstall/archive/2008/03/15/things-in-metadata-that-are-missing-in-reflection.aspx"&gt;Metadata that aren't exposed in Reflection&lt;/a&gt;.&amp;nbsp; Here's an opposite case. &lt;/p&gt; &lt;p&gt;While metadata represents static bits on disk, Reflection operates in a live process with access to the CLR's loader. So reflection can represent things the CLR loader and type system may do that aren't captured in the metadata.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;For example, an array T[] may implement interfaces, but which set of interfaces is not captured in the metadata. So consider the following code that prints out the interfaces an int[] implements:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;using&lt;/span&gt; System;

&lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Foo
&lt;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Main()
    {
        &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: rgb(163,21,21)"&gt;"Hi"&lt;/span&gt;);
        &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: rgb(43,145,175)"&gt;Environment&lt;/span&gt;.Version);
        &lt;span style="color: rgb(43,145,175)"&gt;Type&lt;/span&gt;[] t2 = &lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt;[]).GetInterfaces();
        &lt;span style="color: rgb(0,0,255)"&gt;foreach&lt;/span&gt; (&lt;span style="color: rgb(43,145,175)"&gt;Type&lt;/span&gt; t &lt;span style="color: rgb(0,0,255)"&gt;in&lt;/span&gt; t2)
        {
            &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.WriteLine(t.FullName);
        }
        &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: rgb(163,21,21)"&gt;"done"&lt;/span&gt;);
    }
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/blockquote&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Compile it once for v1.0. Then run the same binary against v1 and v2.&amp;nbsp; It's the same file (and therefore same metadata) in both cases. &lt;br&gt;The V1 case is inconsistent because it doesn't show any interfaces, it should at least show a few builtins like IEnumerable (typeof(IEnumerable).IsAssignableFrom(typeof(int[])) == True). But in the v2 case, you see reflection showing the interfaces, particularly the new 2.0 generic interfaces, that the CLR's type system added to the the array. So the V2 list is not the same as the V1 list, but this difference is not captured in the metadata. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;pre&gt;&lt;b&gt;&lt;span style="color: rgb(0,0,160)"&gt;C:\temp&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: rgb(164,0,0)"&gt;c:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\csc.exe t.cs&lt;/span&gt;&lt;/i&gt;
Microsoft (R) Visual C# .NET Compiler version 7.10.6001.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.


&lt;b&gt;&lt;span style="color: rgb(0,0,160)"&gt;C:\temp&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: rgb(164,0,0)"&gt;t.exe&lt;/span&gt;&lt;/i&gt;
Hi
1.1.4322.2407
done

&lt;b&gt;&lt;span style="color: rgb(0,0,160)"&gt;C:\temp&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: rgb(164,0,0)"&gt;set COMPLUS_VERSION=v2.0.50727&lt;/span&gt;&lt;/i&gt;

&lt;b&gt;&lt;span style="color: rgb(0,0,160)"&gt;C:\temp&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: rgb(164,0,0)"&gt;t.exe&lt;/span&gt;&lt;/i&gt;
Hi
2.0.50727.1433
System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.Generic.IList`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
System.Collections.Generic.ICollection`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
System.Collections.Generic.IEnumerable`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
done

&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8536681" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author><category term="Compilers &amp;amp; Languages" scheme="http://blogs.msdn.com/jmstall/archive/tags/Compilers+_2600_amp_3B00_+Languages/default.aspx" /></entry><entry><title>Nice MSDN URLs</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/05/19/nice-msdn-urls.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/05/19/nice-msdn-urls.aspx</id><published>2008-05-19T23:46:34Z</published><updated>2008-05-19T23:46:34Z</updated><content type="html">&lt;p&gt;I noticed that MSDN finally has nice URLs for the BCL. (Or perhaps that should be "I finally noticed that ...", depending on how long this has been)&lt;/p&gt; &lt;p&gt;So instead of:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/1009fa28.aspx"&gt;http://msdn.microsoft.com/en-us/library/1009fa28.aspx&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;You can do:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.assembly.loadfrom.aspx"&gt;http://msdn.microsoft.com/en-us/library/system.reflection.assembly.loadfrom.aspx&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;For overloaded methods, it takes you to the disambiguation page. &lt;/p&gt; &lt;p&gt;This actually makes it a lot easier to find BCL APIs when you know the name. Now most of the time, I can just type the name right into the URL. And I have a higher confidence that this link won't get broken. &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8519674" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author></entry><entry><title>The price of complexity</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/04/23/the-price-of-complexity.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/04/23/the-price-of-complexity.aspx</id><published>2008-04-23T08:03:37Z</published><updated>2008-04-23T08:03:37Z</updated><content type="html">&lt;p&gt;My house was haunted. One of the lights would randomly go on or off and random times without anybody fiddling the switch. &lt;/p&gt; &lt;p&gt;The previous owner of our house had installed fancy dimmer light switches. On a whim, we replaced one of the fancy switches with a simple on/off switch.&amp;nbsp; As we took the old fancy switch out, we noticed that it had capacitors, a circuit board, resistors, even a microchip! That's a lot of different things to break down. &lt;/p&gt; &lt;p&gt;The new simple switch worked great, and the associated light no longer randomly toggles. So I conclude the fancy light switch was the problem. &lt;/p&gt; &lt;p&gt;Furthermore, the dimmer switches were more complicated to use because they had some fancy pressure touch thing: a quick fast press would toggle the light; a soft press would dim the light. It took us a while to get used to them. &lt;/p&gt; &lt;p&gt;When I was at Home Depot, the fancy switches were $40; whereas the simple on/off switches were ~$3.&amp;nbsp; The old simple switches throughout our house are still working; and we never really needed the dimming features for the fancy switches. &lt;/p&gt; &lt;p&gt;&lt;em&gt;So the fancy switches were more expensive, harder to use, and haunted&lt;/em&gt;. Overall, not an ideal tradeoff for our needs. We'll stick with the simple on/off switches.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;em&gt;I think the same things applies to software design&lt;/em&gt;. You can build complicated software with lots of features, but that also means more places where it could break down. If a simple solution does the trick, it may not only be cheaper to build, but easier to use and cheaper to maintain in the long run.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8418126" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author></entry><entry><title>Codegen for On Error Resume Next</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/04/12/codegen-for-on-error-resume-next.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/04/12/codegen-for-on-error-resume-next.aspx</id><published>2008-04-12T07:22:32Z</published><updated>2008-04-12T07:22:32Z</updated><content type="html">&lt;p&gt;VB has a "&lt;a href="http://msdn2.microsoft.com/en-us/library/5hsw66as(VS.80).aspx"&gt;On Error Resume Next&lt;/a&gt;", which tells each line to swallow exceptions and just keep executing to the next line. It's kind of like a try-catch around every single line. &lt;/p&gt; &lt;p&gt;It may be tempting for C++ developers to make fun of VB for this, but this is a lot like programming with HRESULT (or any error handling strategy based on return codes) when you forget to check the return value. And as we look at the codegen below, VB's code could turn out to be even more efficient than the unmanaged error handling equivalent.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So in this VB snippet, the exception is is swallowed and "Next" is printed. &lt;/p&gt; &lt;blockquote&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;Module&lt;/span&gt; Module1

    &lt;span style="color: rgb(0,0,255)"&gt;Sub&lt;/span&gt; Main()
        &lt;span style="color: rgb(0,0,255)"&gt;On&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Error&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Resume&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Next
&lt;/span&gt;        Console.WriteLine(&lt;span style="color: rgb(163,21,21)"&gt;"Hello!"&lt;/span&gt;)
        &lt;span style="color: rgb(0,0,255)"&gt;Throw&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; Exception(&lt;span style="color: rgb(163,21,21)"&gt;"Bong!"&lt;/span&gt;)

        Console.WriteLine(&lt;span style="color: rgb(163,21,21)"&gt;"Next"&lt;/span&gt;)
    &lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub

End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Module&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you're wondering what the codegen is like, you can always compile and then view the IL in ildasm. Or you can view it in Reflector as C#&amp;nbsp; instead of IL, which is easier to comprehend. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="code"&gt;[&lt;span style="color: rgb(0,0,255)"&gt;STAThread]
&lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;public &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;static &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;void &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;Main()
{
    &lt;/span&gt;&lt;span style="color: rgb(128,128,128)"&gt;// &lt;/span&gt;&lt;span style="color: rgb(128,128,128)"&gt;This item is obfuscated and can not be translated.
    &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;int VB$ResumeTarget;
    &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;try
    {
        &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;int VB$CurrentStatement;
    Label_0001:
        &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;ProjectData.&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;ClearProjectError();
        &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;int VB$ActiveHandler = &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;-2;
    Label_0009:
        VB$CurrentStatement = &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;2;
        &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;Console.&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;WriteLine(&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;"Hello!");
    Label_0016:
        VB$CurrentStatement = &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;3;
        &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;throw &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;new &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;Exception(&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;"Bong!");
    Label_0023:
        VB$CurrentStatement = &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;4;
        &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;Console.&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;WriteLine(&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;"Next");
        &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_009E;
    Label_0035:
        VB$ResumeTarget = &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;0;
        &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;switch ((VB$ResumeTarget + &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;1))
        {
            &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;case &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;1:
                &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_0001;

            &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;case &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;2:
                &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_0009;

            &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;case &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;3:
                &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_0016;

            &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;case &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;4:
                &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_0023;

            &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;case &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;5:
                &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_009E;

            &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;default:
                &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_0093;
        }
    Label_0059:
        VB$ResumeTarget = VB$CurrentStatement;
        &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;switch (((VB$ActiveHandler &amp;gt; &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;-2) ? VB$ActiveHandler : &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;1))
        {
            &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;case &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;0:
                &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_0093;

            &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;case &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;1:
                &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_0035;
        }
    }
    &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;catch (&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;object obj1) &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;when (&lt;/span&gt;&lt;span style="color: rgb(128,128,128)"&gt;?)
    {
        &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;ProjectData.&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;SetProjectError((&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;Exception) obj1);
        &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;goto Label_0059;
    }
Label_0093:
    &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;throw &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;ProjectData.&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;CreateProjectError(&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;-2146828237);
Label_009E:
    &lt;/span&gt;&lt;span style="color: rgb(0,0,128)"&gt;if (VB$ResumeTarget != &lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;0)
    {
        &lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;ProjectData.&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;ClearProjectError();
    }
}
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So you can see it's just putting the entire region in a try/catch block, and then using a switch table to jump back to the appropriate line.&amp;nbsp; It has a "Current Statement" variable to track the last successful line to execute before an exception may have been thrown, and then switches to the next line on the exception path. &lt;/p&gt;
&lt;p&gt;The switch table may seem evil at first, but remember that in native code, all those IfFailGoto() checks to propagate return results also add up to a lot of switching code. In this case, the branches are at least optimized into a single switch table as opposed to scattered branch code. &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8383912" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author><category term="Compilers &amp;amp; Languages" scheme="http://blogs.msdn.com/jmstall/archive/tags/Compilers+_2600_amp_3B00_+Languages/default.aspx" /></entry><entry><title>The waiting game</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/04/02/the-waiting-game.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/04/02/the-waiting-game.aspx</id><published>2008-04-03T06:35:43Z</published><updated>2008-04-03T06:35:43Z</updated><content type="html">&lt;p&gt;Punting on a problem can be good or bad, depending on the situation. Punting is not always retreating or surrendering. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Punting is good when the problem will be easier to solve later. &lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;For example, maybe you suspect something may happen that will render the problem moot (eg, a product would be discontinued).&amp;nbsp; &lt;/li&gt; &lt;li&gt;Maybe you'll have more relevant information later that lets you inject some simplifying assumptions.&amp;nbsp; &lt;/li&gt; &lt;li&gt;Maybe you'll have new technologies / options available later than make it easier to solve. &lt;/li&gt; &lt;li&gt;Sometimes, some problems just work themselves out over time because the decisions to an ambiguous problem are answered by the decisions to a clear problem (see &lt;a href="http://blogs.msdn.com/jmstall/archive/2006/02/10/e-pi-i-equals-minus-1.aspx"&gt;e^pi&amp;nbsp; = -1&lt;/a&gt;).&amp;nbsp; &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Punting is bad when the problem gets harder to solver later.&lt;/strong&gt; &lt;/p&gt; &lt;ol&gt; &lt;li&gt;Maybe you're accumulating debt until you solve it. I find this is often the case with &lt;a href="http://msdn2.microsoft.com/en-us/library/bb429476(vs.80).aspx"&gt;FxCop&lt;/a&gt; - I like to get FxCop enabled sooner rather than later because it's easier to stay at 0 errors once you get to 0 errors.&amp;nbsp; &lt;/li&gt; &lt;li&gt;Debt accumulation also happens if future components will be broken until you fix some problem. &lt;/li&gt; &lt;li&gt;Or maybe not having the problem solved is holding you hostage on solving other things.&lt;/li&gt; &lt;li&gt;Maybe punting screws up your dependencies. &lt;/li&gt;&lt;/ol&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8353003" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author></entry><entry><title>Understand the end-to-end scenarios</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/03/27/understand-the-end-to-end-scenarios.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/03/27/understand-the-end-to-end-scenarios.aspx</id><published>2008-03-28T05:11:30Z</published><updated>2008-03-28T05:11:30Z</updated><content type="html">&lt;p&gt;If you don't understand the end-to-end scenario, it's easy to do something that is ultimately self-defeating. &lt;/p&gt; &lt;p&gt;For example, my 3yr old daughter recently learned to play &lt;a href="http://en.wikipedia.org/wiki/Hide_and_seek"&gt;hide-and-seek&lt;/a&gt;. The goal of the game is to hide and avoid being found while the "it" player searches for you. &lt;/p&gt; &lt;p&gt;She's got the part about hiding down. But then once hidden, she shouts out "Daddy, come and find me!!". Given that I'm not deaf, it's kind of self-defeating.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;But seriously..&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;This comes up often in performance scenarios. We've all heard some story where somebody tries a premature optimization and it ends up slowing things down. For example, somebody goes and adds caching to something, and the &lt;a href="http://blogs.msdn.com/jmstall/archive/2008/02/12/why-are-you-caching-data.aspx"&gt;overhead of maintaining the cache&lt;/a&gt; drowns out any perf wins. &lt;/p&gt; &lt;p&gt;Another example is adding some cool feature that's an innate security hole. &lt;/p&gt; &lt;p&gt;A more general example is adding an feature X, but you need feature Y in order to use X.&amp;nbsp; For example, to &lt;a href="http://blogs.msdn.com/jmstall/archive/2005/01/15/353717.aspx"&gt;create a new ICorDebug object in CLR V2&lt;/a&gt;, you needed to pass a version string of the debuggee. But V1 didn't have a way to get a version string from a running process, so we also had to add a 2nd new API, &lt;a href="http://msdn2.microsoft.com/en-us/library/ms232092.aspx"&gt;mscoree!GetVersionFromProcess&lt;/a&gt; in order to enable the attach scenarios.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8340778" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author><category term="Family" scheme="http://blogs.msdn.com/jmstall/archive/tags/Family/default.aspx" /></entry><entry><title>Sometimes it's the obvious answer</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/03/22/sometimes-it-s-the-obvious-answer.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/03/22/sometimes-it-s-the-obvious-answer.aspx</id><published>2008-03-23T05:53:43Z</published><updated>2008-03-23T05:53:43Z</updated><content type="html">&lt;p&gt;Sometimes the answer to a question is so obvious that we skip over it looking for a fancier answer. &lt;/p&gt; &lt;p&gt;Example: A chair at my house had a bunch of little indentations on the seat - kind of like what you'd expect if somebody took a math compass and poked the chair a bunch of times. &lt;/p&gt; &lt;p&gt;I had some friends over and asked them what they thought caused the indentations. They guessed things like:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;did you set something on top of it such as another chair?&lt;/li&gt; &lt;li&gt;did the buttons on somebody's pants scratch it?&lt;/li&gt; &lt;li&gt;did it get accidentally bumped a bunch of times?&lt;/li&gt; &lt;li&gt;did you drop a box of nails on it?&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;No. My 3 year old took a math compass and poked the chair a bunch of times. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;But seriously ... &lt;/strong&gt;&lt;br&gt;I noticed this with threading bugs. Sometimes I'd look at a crash dump of a race condition. I'd have no live repro and would be pouring over the sources trying to infer what the race could be. The &lt;a href="http://blogs.msdn.com/jmstall/archive/2008/01/30/why-threading-is-hard.aspx"&gt;search space for race conditions is huge&lt;/a&gt;, and I'd often find some crazy 15 step race ("the user presses 3 buttons within 10 ms while 4 threads happen to be at certain spots"). But while that was technically a bug, it turned out that was never the real problem. The real problem would always be much simpler. &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8331935" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author><category term="Family" scheme="http://blogs.msdn.com/jmstall/archive/tags/Family/default.aspx" /></entry><entry><title>Arguing by-example vs. by-principle</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/jmstall/archive/2008/03/17/arguing-by-example-vs-by-principle.aspx" /><id>http://blogs.msdn.com/jmstall/archive/2008/03/17/arguing-by-example-vs-by-principle.aspx</id><published>2008-03-17T16:00:50Z</published><updated>2008-03-17T16:00:50Z</updated><content type="html">&lt;p&gt;You can argue by providing examples supporting your case.&amp;nbsp; Alternatively, you can argue by appealing to more general principles. &lt;/p&gt; &lt;p&gt;For example, in arguing that "exposing public fields is bad," you could say:&lt;br&gt;By-principle: "It breaks abstraction and encapsulation."&lt;br&gt;By-example: "This untrusted plugin could set field m_foo to value 4 and cause a null-reference exception on line 16 of file widget.cs".&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="727" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="148"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="307"&gt;&lt;strong&gt;By example&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="266"&gt;&lt;strong&gt;By principle&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="150"&gt;When it's good&lt;/td&gt; &lt;td valign="top" width="307"&gt;Sometimes an example / counter-example can clearly illustrate a problem in an undeniable way. (&lt;a href="http://blogs.msdn.com/jmstall/archive/2006/03/07/cant-have-too-much-chocolate.aspx"&gt;example&lt;/a&gt;)&lt;/td&gt; &lt;td valign="top" width="266"&gt;Can rapidly prune the decision tree and avoid wasting time in overly specific discussions that would ultimately lead to a dead-end.&amp;nbsp; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="152"&gt;Abstraction level&lt;/td&gt; &lt;td valign="top" width="307"&gt;low - uses specific data points&lt;/td&gt; &lt;td valign="top" width="266"&gt;high - uses generalizations&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="154"&gt;When it's bad&lt;/td&gt; &lt;td valign="top" width="307"&gt;This puts a burden on coming up with the "killer example", which you may not be able to do until it's too late. You can waste a lot of time trying to come up with specific examples. The inability to come up with a specific killer example can lead to a false sense of security. (Just because I can't find&amp;nbsp; a bug in your code does not mean it's bug-free.)&lt;/td&gt; &lt;td valign="top" width="266"&gt;Principles may be more subjective and may be more complicated to process. &lt;br&gt;Principles can be easily misapplied. (eg, "My principle is that our code should never crash; therefore I'm going to explicitly put null checks before every pointer access").&lt;br&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="155"&gt;&lt;a href="http://blogs.msdn.com/jmstall/archive/2007/04/15/myers-briggs.aspx"&gt;Myers-Briggs&lt;/a&gt; of target audience&lt;/td&gt; &lt;td valign="top" width="307"&gt;S (sensory)&lt;/td&gt; &lt;td valign="top" width="266"&gt;N (intuitive)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8236154" width="1" height="1"&gt;</content><author><name>jmstall</name><uri>http://blogs.msdn.com/members/jmstall.aspx</uri></author><category term="Random" scheme="http://blogs.msdn.com/jmstall/archive/tags/Random/default.aspx" /></entry></feed>