<?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">Joel Pobar's CLR weblog</title><subtitle type="html">CLR Program Manager: Reflection, LCG, Generics and the type system...</subtitle><id>http://blogs.msdn.com/joelpob/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/joelpob/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2004-04-23T13:47:00Z</updated><entry><title>Leaving Microsoft</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2006/09/29/776652.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2006/09/29/776652.aspx</id><published>2006-09-29T10:33:00Z</published><updated>2006-09-29T10:33:00Z</updated><content type="html">&lt;P&gt;Hi all, &lt;/P&gt;
&lt;P&gt;I've decided - with lots of thought and deliberation -&amp;nbsp;to take a "tinkering" break (sabbatical?) over the next little&amp;nbsp;while:&amp;nbsp;grok some cool new software areas and hang out with the family. I'll hopefully be taking a look at stuff like&amp;nbsp;machine&amp;nbsp;learning, natural language processing and more programming language goodness. You can follow&amp;nbsp;the ramblings at my new blog location: &lt;A href="http://callvirt.net/blog"&gt;http://callvirt.net/blog&lt;/A&gt;, posts should be more regular... ;)&lt;/P&gt;
&lt;P&gt;thanks!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=776652" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>MSDN TV: CLR Method Dispatch Internals</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2005/11/04/489131.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2005/11/04/489131.aspx</id><published>2005-11-04T20:19:00Z</published><updated>2005-11-04T20:19:00Z</updated><content type="html">&lt;P&gt;&lt;A href="http://www.bluebytesoftware.com/"&gt;Joe Duffy&lt;/A&gt; and I recently did an &lt;A href="http://msdn.microsoft.com/msdntv/episode.aspx?xml=episodes/en/20051103CLRJP/manifest.xml"&gt;MSDN TV stint on Method Dispatch Internals&lt;/A&gt;. Joe concentrated on the static end of the spectrum, while I talked about late-bound binding and dynamic calling convention. &lt;/P&gt;
&lt;P&gt;I also &lt;A href="http://www.dcooney.com/ViewEntry.aspx?ID=459"&gt;appeared&lt;/A&gt; with fellow &lt;A href="http://www.dcooney.com/"&gt;Australian&lt;/A&gt; &lt;A href="http://www.patrickcooney.com/weblog.aspx"&gt;Microsofties&lt;/A&gt; at the recent Whidbey Ship party. Lots of fun!&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=489131" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>Good For Nothing Compiler (PDC - TLN410) and other goodies</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2005/10/04/476965.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2005/10/04/476965.aspx</id><published>2005-10-04T21:26:00Z</published><updated>2005-10-04T21:26:00Z</updated><content type="html">Joe Duffy and I were really impressed with the amount of people who showed up for the PDC session “Write a Dynamic Language compiler in an hour” at the PDC last month. It confirmed my belief that customers care for details about compiler technologies and the managed libraries that enable them. We promised source download from commnet and our blogs, so here it is:&amp;nbsp;&lt;BR&gt;&lt;BR&gt;&lt;A href="http://www.bluebytesoftware.com/code/05/10/GfnCompiler.zip"&gt;http://www.bluebytesoftware.com/code/05/10/GfnCompiler.zip&lt;BR&gt;&lt;/A&gt;&amp;nbsp;&lt;BR&gt;&lt;BR&gt;Thanks &lt;A href="http://dcooney.com/"&gt;Dominic&lt;/A&gt;, for your help on the &lt;A href="http://www.codecampoz.com/"&gt;original presentation&lt;/A&gt;, much appreciated!&amp;nbsp;&lt;BR&gt;&lt;BR&gt;What follows are resources I found useful to get bootstrapped in to the world of compiler construction. If you have any other resources you'd like to see appear on this list, drop me an email.&lt;BR&gt;&lt;STRONG&gt;&lt;SPAN style="BACKGROUND-COLOR: #ffffff"&gt;&lt;BR&gt;&lt;BR&gt;Tools, Languages, Source and more...:&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;A href="http://www.plas.fit.qut.edu.au/gppg/Default.aspx"&gt;GPPG (The Gardens Point Parser Generator)&lt;/A&gt;: Yacc/Bison like parser generator that emits C#. This was just released recently, and looks pretty solid.&amp;nbsp; If you look on the link, the QUT folk talk about this being built for a "Ruby .NET" project in the context of parsing the full Ruby grammar. There doesn't seem to be anything mentioned officially about the Ruby .NET project but given their track record on delivery, I'm happy to get my hopes up. Can't wait to get my hands on it!&lt;BR&gt;&lt;BR&gt;&lt;A href="http://www.plas.fit.qut.edu.au/perwapi/Default.aspx"&gt;PEAPI and PERWAPI&lt;/A&gt;: Managed API for reading and writing managed executables. It's a lower level Reflection.Emit like interface, gives you more control over the metadata bits and bytes. I believe the Mono C# compiler uses PERWAPI as it's backend. Fast too.&lt;BR&gt;&lt;BR&gt;&lt;A href="http://www.gotdotnet.com/workspaces/workspace.aspx?id=ad7acff7-ab1e-4bcb-99c0-57ac5a3a9742"&gt;IronPython&lt;/A&gt;: Python compiler for .NET, incubated in my team, the CLR, fronted by &lt;a href="http://blogs.msdn.com/hugunin/"&gt;Jim Hugunin&lt;/A&gt;. A full dynamic language compiler with source, released under a liberal Shared Source license. We're getting close to 1.0 release on this one.&lt;SPAN style="BACKGROUND-COLOR: #ffffff"&gt;&lt;STRONG&gt; &lt;/STRONG&gt;I think this is a great starting point for anyone looking to write or port a dynamic language - Python has some interesting problems and solutions around interop (language, BCL, etc.), performance (late-bound binding and invocation), code loading, IDE integration and more. It has a very active community.&lt;BR&gt;&lt;BR&gt;&lt;A href="http://research.microsoft.com/projects/ilx/fsharp.aspx"&gt;F#&lt;/A&gt;: A functional language with ML like flavor from &lt;a href="http://blogs.msdn.com/dsyme"&gt;Don Syme&lt;/A&gt; at MSR Cambridge. Very stable, fantastic VS.NET integration (both 2003 and 2.0 Beta 2) and the F# to BCL interop stuff is awesome. Lately, Don has been expanding the breadth of F# language features and investing in developer compiler interactivity (IDE/REPL etc.) to make it play great in the .NET ecosystem. I'd love to see an F# book though - mapping OCaml to F# can be tedious if you've never approached either before. &lt;BR&gt;&lt;BR&gt;&lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=3A1C93FA-7462-47D0-8E56-8DD34C6292F0&amp;amp;displaylang=en"&gt;Rotor (SSCLI)&lt;/A&gt;: Subset source to the Common Language Runtime, C# and JScript.NET compilers, shipped with an academic/hobbiest friendly license. Runs on multiple platforms and architectures (Windows, FreeBSD, MacOS - x86, PPC). It's great having the source to the CLR, C# and JScript.NET handy. I recommend buying the Rotor book (see below) if you want to ramp quickly on the source. &lt;BR&gt;&lt;BR&gt;&lt;A href="http://msdn.microsoft.com/netframework/ecma/"&gt;ECMA Specification&lt;/A&gt;: Submission of the CLI (Common Language Infrastructure) to the ECMA standards organization. More commonly known as "the docs to the product". Has all the execution semantics, rules and metadata bits of the CLR - exellent resource for compiler writers.&lt;BR&gt;&lt;BR&gt;&lt;a href="http://blogs.msdn.com/admin/blogs/www.dotnetpowered.com/languages.aspx"&gt;List of .NET Languages&lt;/A&gt;: A pretty complete list of languages that run on top of the CLR/.NET platform. Has a lot of links to the respective project websites. Some of the languages come with source too. &lt;BR&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;A href="http://discuss.microsoft.com/archives/dotnet-language-devs.html"&gt;DOTNET-LANGUAGE-DEVS&lt;/A&gt;: This is the place where commercial, academic and hobbiest compiler writers hang out. The list is light on traffic, but you can usually expect a rapid response to questions. &lt;BR&gt;&lt;BR&gt;&lt;A href="http://discuss.develop.com/dotnet-clr.html"&gt;DOTNET-CLR&lt;/A&gt;: A mailing list for CLR geeks. Some of the language people hang out on this list. Great place to ask questions about compiler&amp;lt;--&amp;gt;VM problems you might face when targeting the CLR. &lt;BR&gt;&lt;BR&gt;&lt;A href="http://lambda-the-ultimate.org/"&gt;Lambda the Ultimate&lt;/A&gt;: A great programming languages weblog. &lt;BR&gt;&lt;SPAN style="BACKGROUND-COLOR: #ffffff"&gt;&lt;BR&gt;&lt;STRONG&gt;&lt;BR&gt;Technologies:&lt;BR&gt;&lt;BR&gt;&lt;/STRONG&gt;&lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemreflectionemit.asp"&gt;Reflection.Emit MSDN documentation&lt;/A&gt;: Documentation for the Reflection.Emit namespace. Useful if you intend on using Reflection.Emit as the backend for your compiler.&lt;BR&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;a href="http://blogs.msdn.com/joelpob/archive/2004/01/21/61411.aspx"&gt;Hello World, Reflection.Emit style&lt;/A&gt;: Hello, World!&lt;BR&gt;&lt;BR&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/80h6baz2(en-US,VS.80).aspx"&gt;DynamicMethod (Lightweight Code Generation)&lt;/A&gt;: MSDN documentation for LCG. LCG is a Whidbey (2.0) technology for lightweight, GC reclaimable code generation. It uses familiar Reflection.Emit API's. Recommended in most scenarios where code generation is required and assemblies and type generation is not needed.&lt;BR&gt;&lt;BR&gt;&lt;a href="http://blogs.msdn.com/joelpob/archive/2004/03/31/105282.aspx"&gt;Hello World, Lightweight Code Generation (LCG)&lt;/A&gt;: Hello, World, this time using LCG as the code generation technology.&lt;BR&gt;&lt;BR&gt;&lt;A href="http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/"&gt;Reflection Performance article&lt;/A&gt;: An article I wrote a few months back on how to improve the performance of common Reflection scenarios. Has some stuff on LCG and binding. &lt;BR&gt;&lt;BR&gt;&lt;a href="http://blogs.msdn.com/joelpob/archive/2005/07/01/434728.aspx"&gt;Under the hood of Dynamic Languages&lt;/A&gt;: Part 1 of a blog post I did about how dynamic languages map to the runtime. A lot of what I talk about here can be found in source form in the IronPython compiler. Part 2 is coming soon. ;)&lt;BR&gt;&lt;BR&gt;&lt;A href="http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=20fe0475-c693-412e-8077-174664b21a7b"&gt;Whidbey Delegates&lt;/A&gt;: Describes the relaxed signature matching changes we've done for Whidbey in the delegate space. What isn't mentioned is the open instance/closed static delegates that we've added - the Whidbey delegate docs describe these changes but I don't believe the latest docs are on the web yet. These small but powerful additions open up a whole new range of calling convention opportunities, especially in the dynamic languages space.&lt;BR&gt;&lt;BR&gt;&lt;a href="http://blogs.msdn.com/joelpob/archive/2004/04/01/105862.aspx"&gt;Late-bound invocation&lt;/A&gt;: Some notes I wrote up on late-bound invocation using Reflection (if you're going dynamic, then I hope this helps you out). &lt;a href="http://blogs.msdn.com/joelpob/archive/2004/04/23/119171.aspx"&gt;Part 2 here&lt;/A&gt;.&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Compiler books:&lt;BR&gt;&lt;BR&gt;
&lt;TABLE cellSpacing=10 cellPadding=10&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style="HEIGHT: 91px"&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0130622966/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/0130622966.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD style="HEIGHT: 91px" vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0130622966/bluebytesoftw-20/"&gt;Compiling for the .NET Common Language Runtime&lt;/A&gt;, John Gough, 0130622966&lt;BR&gt;&lt;BR&gt;The bible for compiler writers targeting the CLR. &lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0735615470/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/0735615470.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0735615470/bluebytesoftw-20/"&gt;Inside Microosft .NET IL Assembler&lt;/A&gt;, Serge Lidin, 0735615470&lt;BR&gt;&lt;BR&gt;All you need to know about IL and the ILASM/ILDASM tools that ship with the SDK. If your compiler is going to target textual IL and call on the ILASM compiler to cook you up an exe, this book will be invaluable. &lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0201100886/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/0201100886.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0201100886/bluebytesoftw-20/"&gt;Compilers&lt;/A&gt;, Alfred V. Aho, Ravi Sethi, Jeffrey D. Ullman, 0201100886&lt;BR&gt;&lt;BR&gt;The bible. Also featured in the movie &lt;A href="http://www.imdb.com/title/tt0113243/"&gt;Hackers&lt;/A&gt;, as a l33t resource for those hacker people. &lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0521582741/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/0521607647.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0521582741/bluebytesoftw-20/"&gt;Modern Compiler Implementation in ML&lt;/A&gt;, Andrew W. Appel, 0521582741&lt;BR&gt;&lt;BR&gt;I haven't finished reading this book yet, but so far so good. It'd be better if it was "Modern Compiler Implementation in F#", but I'm biased... :) (also somes in C and Java flavors)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/1558604421/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/1558604421.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/1558604421/bluebytesoftw-20/"&gt;Programming Language Pragmatics&lt;/A&gt;, Michael L. Scott, 1558604421&lt;BR&gt;&lt;BR&gt;I love the chapter on concurrent programming languages towards the end of the book. Lots of really great archaic info on languages like Ada, Fortran and Prolog. Great stuff.&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/1558603204/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/1558603204.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/1558603204/bluebytesoftw-20/"&gt;Advanced Compiler Design and Implementation&lt;/A&gt;, Steven Muchnick, 1558603204&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;.&lt;STRONG&gt;NET Platform books&lt;/STRONG&gt;&lt;SPAN style="BACKGROUND-COLOR: transparent"&gt; (useful to understand what you're targeting)&lt;/SPAN&gt;:&lt;BR&gt;&lt;BR&gt;
&lt;TABLE cellSpacing=10 cellPadding=10&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style="HEIGHT: 91px"&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0201734117/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/0201734117.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD style="HEIGHT: 91px" vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0201734117/bluebytesoftw-20/"&gt;Essential .NET, Volume 1: The Common Language Runtime&lt;/A&gt;, Don Box, 0201734117&lt;BR&gt;&lt;BR&gt;Suitably high level to get a good understanding of the CLR. I recommend this one to all CLR newbies.&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/059600351X/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/059600351X.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/059600351X/bluebytesoftw-20/"&gt;Shared Source CLI Essentials&lt;/A&gt;, David Stutz, Ted Neward, Geoff Shilling, 059600351X&lt;BR&gt;&lt;BR&gt;Total ego booster when coupled with the Rotor source. Impress your friends and co-workers with your deep understanding of the CLR. Graduates of this book are prone to be hired by the CLR team. Recommended to compiler writers who want a sharp understanding of what they are targeting.&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0321154932/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/0321154932.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0321154932/bluebytesoftw-20/"&gt;The Common Language Infrastructure Annotated Standard&lt;/A&gt;, Jim Miller, 0321154932&lt;BR&gt;&lt;BR&gt;If you find the ECMA spec lacks a little oomph, try this book from CLR Architect (and part-time opera singer) Jim Miller. Annotates the ECMA spec with design decision explainations and other runtime facts. Also known to produce CLR new hires. &lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0735614229/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/0735614229.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0735614229/bluebytesoftw-20/"&gt;Applied Microsoft .NET Framework Programming&lt;/A&gt;, Jeffrey Richter, 0735614229&lt;BR&gt;&lt;BR&gt;Jeff is the man. A broader platform book that goes a little deeper than Essential .NET. Useful to newbie compiler writers for two reasons: you get to learn the platform API's to write your compiler, and it gives a good insight in to how the backend works.&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0764571354/bluebytesoftw-20/"&gt;&lt;IMG height=75 src="http://images.amazon.com/images/P/0764571354.01.THUMBZZZ.jpg" width=60 border=0&gt;&lt;/A&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;A href="http://www.amazon.com/exec/obidos/ASIN/0764571354/bluebytesoftw-20/"&gt;Professional .NET Framework 2.0&lt;/A&gt;, Joe Duffy, 0764571354&lt;BR&gt;&lt;BR&gt;Where's Joe's face? &lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;BR&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=476965" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>CLR Dynamic languages under the hood (Part 1 of many)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2005/07/01/434728.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2005/07/01/434728.aspx</id><published>2005-07-01T21:24:00Z</published><updated>2005-07-01T21:24:00Z</updated><content type="html">&lt;P&gt;There seems to be a fair amount of recent press and blog action surrounding the dynamic or “scripting” language movement, especially when the context includes virtual machines. While I wont bother commenting on why this is the case, I figured I would cook up a few rough notes (and I do stress that these are just notes) that describe how these languages effectively and efficiently target the CLR - hopefully this will inspire you to start toying with writing or porting a language on your own. I paraphrase what John Gough (Author of Component Pascal&amp;nbsp; &lt;A href="http://www.plas.fit.qut.edu.au/gpcp/Default.aspx"&gt;http://www.plas.fit.qut.edu.au/gpcp/Default.aspx&lt;/A&gt;) stated recently (&lt;A href="http://channel9.msdn.com/ShowPost.aspx?PostID=49330"&gt;http://channel9.msdn.com/ShowPost.aspx?PostID=49330&lt;/A&gt;): “Compilers are fun, they’re full of all kinds of dirty little tricks; you can be really creative because you’re dealing with the nitty gritty down at the bare metal”. I couldn’t agree more. &lt;/P&gt;
&lt;P&gt;Disclaimer:&lt;/P&gt;
&lt;P&gt;I hope this post will end up being the first of a series of posts on technical notes surrounding dynamic languages on the CLR. Once again though, I do stress that these are just loose ideas – there are many many ways to do what I’m showing here, the intent is just to get your brains thinking about the interesting challenges and idea’s surrounding the dynamic language space.&lt;/P&gt;
&lt;P&gt;Secondly – none of this is optimized. The loose idea’s I illustrate are based on hypotheticals and the mapping to the CLR is sometimes far from good (you’ll see boxing, and common perf unfriendly patterns all over the place). Just keep in mind that a good, solid dynamic language compiler has the chance to optimize code for even better performance on the runtime. These optimizations, while interesting, are best left to another post. &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=4&gt;&lt;STRONG&gt;The high level first, please… (skip if necessary)&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;What encapsulates a dynamic language? A few people have been successful in encapsulating full and detailed descriptions (&lt;A href="http://www.tcl.tk/doc/scripting.html"&gt;http://www.tcl.tk/doc/scripting.html&lt;/A&gt;), but I like to think interesting dynamic languages are languages with one or more of the following things: typeless or “loosely typed” language syntax; REPL loop (Read Eval Print Loop); and most importantly, a language runtime or late-binder for expression evaluation at runtime. Of course, dynamic languages are a whole lot more than this, I’ve just constrained this post to ideas around those particular aspects.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Where can I get a CLR based dynamic language so I can follow along&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;IronPython (Python for the CLR) ships with full source: &lt;A href="http://workspaces.gotdotnet.com/ironpython/"&gt;http://workspaces.gotdotnet.com/ironpython/&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;JScript.NET (Javascript for CLR) ships with the framework redist. jsc.exe is the compiler exe, just invoke that. More on JScript here: &lt;A href="http://www.gotdotnet.com/team/jscript/"&gt;http://www.gotdotnet.com/team/jscript/&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;VB.NET – yep, VB.NET could be called a “dynamic language” when you explicitly declare:&lt;BR&gt;Option Strict Off&amp;nbsp; At the top of your vb source file. &lt;/P&gt;
&lt;P&gt;Phalanger (PHP for CLR): &lt;A href="http://www.php-compiler.net/"&gt;http://www.php-compiler.net/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;There are more I’m sure. You might also want to go digging around in this list: &lt;A href="http://www.dotnetpowered.com/languages.aspx"&gt;http://www.dotnetpowered.com/languages.aspx&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Gimme quick definitions: Loosely typed languages&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Your typical C# program (C# being a kind of static language) will cobble together a whole slew of statements, one of which will be a declaration of a variable:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;string s;&lt;BR&gt;Foo foo = new Foo();&lt;BR&gt;...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;“s” and “foo” are variables with the type “string” and “Foo”. If I then try and assign an integer to the “foo” variable, the C# compiler will give me back an error. These compiler errors are because of strong typing rules associated with the language – once you type a variable, it’s hard if not impossible to change that type midway through a code block. Loose typing generally means that there are loose or no typing restrictions (you can do whatever you like really). You can do things like this (IronPython):&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;a = "hello world"&lt;BR&gt;print (a)&lt;BR&gt;a = 1&lt;BR&gt;print (a)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Prints:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;hello world&lt;BR&gt;1&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Strong (or static) typing – declare type and keep it that way. Got it. Dynamic (or loose) typing, type safety not enforced, can reassign variables to whatever instance you like. Got it. &lt;/P&gt;
&lt;P&gt;If you think further about how this maps to the CLR, hopefully you’ll stumble on some interesting questions. How does loose typing pan out in a runtime that has a common type system? What about that verifiability thing the CLR supports, does the verifier allow loosely typed languages to run? What is the actual type of “a”? I’ll answer some of those questions later in the post. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Gimme quick definitions: REPL (Read Eval Print Loop)&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;REPL’s are usually quite simple command line programs that read in a line of text and feed that to a compiler or interpreter for statement or expression evaluation. IronPython supports a REPL loop:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;C:\IronPython-0.7.6\bin&amp;gt;IronPythonConsole.exe&lt;BR&gt;IronPython 0.7.6 on .NET 2.0.50215.44&lt;BR&gt;Copyright (c) Microsoft Corporation. All rights reserved.&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; a = "IronPython has a REPL"&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt; print (a)&lt;BR&gt;IronPython has a REPL&lt;BR&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The bolded stuff is the important part. The “&amp;gt;&amp;gt;&amp;gt; “ is basically a prompt for the next piece of Python code to execute. Each string passed to IronPython’s REPL actually does something (even if it doesn’t print to the screen), mostly because every line in the Python language is a statement (a language design choice I guess). This language semantic is fairly common in dynamic languages.&lt;/P&gt;
&lt;P&gt;Not all dynamic languages have REPL’s, and that’s probably a good thing. I like the warmth of a functional IDE myself.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Gimme quick definitions: Language runtime or Late-binder&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Easiest way to explain this one is with one simple but powerful statement: &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;o.m()&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;“o” being some sort of instance, and “m” being a method. &lt;/P&gt;
&lt;P&gt;In the static language world, the compiler when it comes to figure this one out will know the type of “o” (because it was explicitly defined), and can therefore travel to that type and lookup the method “m”. If it can’t find “m”, it will throw a compiler error in your face. If it can find “m”, the compiler will happily emit IL code that simply does a call to “m”. Quite simple: compile time resolution of “m”, and static invocation of “m” via a call instruction with the metadata token all lined up ready to go. Assuming “o” was typed as Foo, the IL would look like this example: &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;ldloc.0&lt;BR&gt;callvirt&amp;nbsp;&amp;nbsp; instance void Foo::m()&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In the dynamic language world, this statement gets evaluated at run-time, and usually for good reason. Here are a couple of good ones: firstly, dynamic languages are about instance based resolution and invocation at the last possible moment – do away with as many compile time rules as possible; secondly, at compile time the compiler doesn’t know what the type of “o” is, so it’ll need to use the instance to figure out if it even has an “m()” or not; thirdly, there may be rules around language extensibility (yes, some languages allow you to do crazy things like override the “.” operator! Lua (&lt;A href="http://www.lua.org/"&gt;www.lua.org&lt;/A&gt;) is one of my favourite languages because it offers this kind of extensibility), so those rules might need to be run before resolution and invocation. &lt;/P&gt;
&lt;P&gt;So what can a dynamic language compiler do with “o” and “m”? Not much as it turns out, but it needs to emit some sort of code right? The compiler will generally emit code that calls in to a runtime helper to do the resolution and another runtime helper to do the invocation (or maybe both is done in the same helper method). Let’s have a look at what VB.NET with Option Strict Off does: &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Option Strict Off&lt;BR&gt;...&lt;BR&gt;Dim o&lt;BR&gt;o.m()&lt;BR&gt;...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The IL code looks like this: &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;ldloc.0&lt;BR&gt;ldnull&lt;BR&gt;ldstr&amp;nbsp; "m"&lt;BR&gt;ldc.i4.0&lt;BR&gt;newarr [mscorlib]System.Object&lt;BR&gt;ldnull&lt;BR&gt;ldnull&lt;BR&gt;ldnull&lt;BR&gt;ldc.i4.0&lt;BR&gt;call&amp;nbsp;&amp;nbsp; object Microsoft.VisualBasic.CompilerServices.NewLateBinding::LateCall(object,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; class [mscorlib]System.Type,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object[],&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string[],&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; class [mscorlib]System.Type[],&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool[],&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;The three interesting parts are bolded: ldloc.0, ldstr “m” and the call to the method “NewLateBinding::LateCall”. LateCall is taking (along with other things) an instance (the ldloc) and a string name representing the method (ldstr “m”). If you think a little ahead, what can you do with an instance and a string name? Reflection baby, Reflection! That’s exactly what the VB.NET latebinder ends up doing – Reflecting on the “o” instance to find “m”, then a .Invoke() to actually invoke the method it finds.&lt;/P&gt;
&lt;P&gt;Okay, there are your quick definitions. Let’s look at some technical details on how some of this stuff works.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=4&gt;&lt;STRONG&gt;Latebinder for callsites&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Let’s look at a hypothetical example of a callsite and the late binder (the language below is imaginary so ignore that part):&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Foo&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;void m(o)&lt;BR&gt;&amp;nbsp;{}&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;// part we're generating code for&lt;BR&gt;o = Foo.ctor()&lt;BR&gt;o.m("test")&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;When our hypothetical dynamic language compiler runs across these two statements, it must generate code that forwards this request to a latebound language runtime. We’ve seen this kind of thing in the example above with VB.NET, but I can’t share the latebinder code for VB.NET so we’re contriving our own:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;.locals init (object V_0)&lt;BR&gt;newobj&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance void Foo::.ctor()&lt;BR&gt;stloc.0&lt;BR&gt;ldloc.0&lt;BR&gt;ldstr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "m"&lt;BR&gt;ldstr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "test"&lt;BR&gt;call&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object [LateBinder]LateBinder::Call(object, string, object)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Code for our hypothetical late-binder:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;public class LateBinder&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; public static object Call(object o, string name, object arg)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return o.GetType().GetMethod(name).Invoke(o, new object[] { arg });&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The IL sets up the “o.m()” callsite as a early-bound call to our LateBinder::Call method, which calls the “m” method using Reflection late-bound. &lt;/P&gt;
&lt;P&gt;There are a few obvious situations we’ve missed with this small hypothetical example. Calls on static methods is one (simple enough, don’t bother passing in the “this” pointer). Calls to methods with more than one argument (again, simple enough, generate code that packs the arguments in to a temporary array, and create a Call overload that takes: object[] args as an argument) another. A couple of other issues/situations to think about: calls to methods that return void when LateBinder::Call return object, calls to methods with params, calling convention issues – does the dynamic language support OO style virtual calls, performance of the calls. I’ll tackle some of these issues at a later date.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=4&gt;&lt;STRONG&gt;Loose typing on a static virtual machine&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;It’s been said that the CLR isn’t too good a place for dynamic languages, mostly inferences gathered because of the inherit static nature of the CIL instructions, type and signature matching, and the CLS (Common Language Specification) and CTS (Common Type System). This is first evident when a compiler developer goes to make his or her first decision – what are my languages types, and how do they map to the CLR’s CTS? There are many common types that are provided by the runtime, and I’ve previously gone in to them here (&lt;a href="http://blogs.msdn.com/joelpob/archive/2004/07/19/187709.aspx"&gt;http://blogs.msdn.com/joelpob/archive/2004/07/19/187709.aspx&lt;/A&gt;). The question I want to draw is this one, if I have the following:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Dim o&lt;BR&gt;o.m()&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Or back to the IronPython example:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;a = "hello world"&lt;BR&gt;a = 1&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;What type is “o” and “a”? When a compiler goes to emit code for this, it must specify in metadata the type of the variable. You can see these type declarations in ILDASM output, locals are declared with type in the .locals section, parameters are declared with type in the method signature, and members (fields, events, delegates etc) are also strongly typed. &lt;/P&gt;
&lt;P&gt;Back to “o” and “a”. Given that these would probably be locals to a method, we need to give them a type as part of declaration, yet still be able to reassign that variable with any other instance of any given type. Enter good ‘ol polymorphism. Everything derives from System.Object, so therefore I can assign any instance of any type (including valuetypes if you box them) to an instance typed as System.Object. If you crack open the result from VB.NET or IronPython (Jscript .NET is another good example) you can verify this for yourself.&lt;/P&gt;
&lt;P&gt;*** Note ****&lt;BR&gt;Of course there are alternatives to using System.Object. If the language you’re mapping doesn’t require BCL or cross-language interoprerability, you can pretty much do whatever you like in your self contained world.&lt;/P&gt;
&lt;P&gt;What about methods generated by a dynamic language? Yep – the signatures almost always have parameters and returns typed as object. Crack open a IronPython method: &lt;/P&gt;
&lt;P&gt;IronPython code:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;def saysomething(a):&lt;BR&gt;&amp;nbsp;print (a)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;a = "hello world"&lt;BR&gt;saysomething(a)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;ILDASM output:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;.method public static object saysomething$f0 (object a) cil managed&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;ldarg.0&lt;BR&gt;&amp;nbsp;call void [IronPython]IronPython.Objects.Ops::Print(object)&lt;BR&gt;&amp;nbsp;ldnull&lt;BR&gt;&amp;nbsp;ret&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;You’ll notice a couple of things here. Firstly, saysomething is a static method, returns object and takes an object. Secondly, the call to the IronPython “print” method takes an object as a parameter.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Problems with everything being object&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;With this in mind, consider for a second your typical Base Class Library – we try our best to be accomodating, but given the strongly typed nature of the BCL, you can imagine that your dynamic language where everything is typed as object, might have issues trying to call on it’s Base Class Library counterparts that are all strongly typed, and visa versa. &lt;/P&gt;
&lt;P&gt;Consider this BCL callsite case:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;a = "hello world"&lt;BR&gt;Console.WriteLine(a)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Where Console.WriteLine has some of the following overloads:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;WriteLine(string, object, object, object)&lt;BR&gt;WriteLine(string, object object)&lt;BR&gt;WriteLine(char[])&lt;BR&gt;// ...&lt;BR&gt;WriteLine(string)&lt;BR&gt;WriteLine(object)&lt;BR&gt;// ...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;WriteLine has 19 overloads in all, 12 of which take 1 argument. Given that “a” is typed as object, which overload do you pick? Well thankfully “WriteLine” has an overload that takes object, so the compiler can safely bind to that one without any issues, but what about the cases where there exists no overloads that take object, such as:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Console.SetWindowSize(int, int)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;w = 100&lt;BR&gt;h = 100&lt;BR&gt;Console.SetWindowSize(w, h)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;“w” and “h” are both typed as object (in this case both “w” and “h” are most likely objects holding on to boxed ints, depending on how the language treats numbers under the hood), and runtime rules don’t allow calls to be made to a method taking two ints when passing in two objects – it’s not verifiable (although a program like this will run in full trust, use ildasm/asm and try it). This derives a question – how do you resolve (find), bind to and call a BCL method from a dynamic language? This can usually be done in the late-binder using Reflection, with a whole bunch of magic code to fill in the gaps in Reflections coercion/casting semantics.&lt;/P&gt;
&lt;P&gt;What about BCL callback mechanisms, delegates and events? Given that methods take and return objects as parameters, how do you hook up one of these methods to an event when a delegate may be statically typed as void MyDelegate(string s)? I solve this and the rest of these “loose typing” problems later on in the post (yes I know, another forward reference, but be patient!).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;IL instructions are typed, what happens now?&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;I’ll talk about a simple case here – you’ll have to use your imagination to extrapolate all the other problems associated with IL typing. Consider the following C# expression&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;2 + 4&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The IL sequence that the C# compiler will emit is as follows:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;ldc.i4.2&lt;BR&gt;ldc.i4.4&lt;BR&gt;add&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;“ldc.i4” pushes a supplied value of type int32 onto the evaluation stack as an int32. In this case, the .2 and .4 part is an alias to ldc.i4 number. The “add” instruction adds two values that are popped from the stack together and pushes the result on to the stack. There are some rules over what types “add” can pop from the stack – namely, the type of the element must be a “number” (number being things like int32, int64, natural int, float etc – the actual list can be found on msdn). Add can’t add together a Foo and Bar. Simple right?&lt;/P&gt;
&lt;P&gt;What about our simple dynamic language case, where everything is typed as object? The “add” instruction can’t add together objects, it’s not supported (and not correct either), so what can a dynamic language do? It can generate code to a latebound “Add” method in the language runtime that will do the necessary type casting to perform the add operation.&lt;/P&gt;
&lt;P&gt;The Add method might look like this in the language runtime:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;public static object Add(object o1, object o2)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;if (o1.GetType() == typeof(double) &amp;amp;&amp;amp; o2.GetType() == typeof(double))&lt;BR&gt;&amp;nbsp;&amp;nbsp; return ((double)o1) + ((double)o2);&lt;BR&gt;&amp;nbsp;else if (o1.GetType() == typeof(int) &amp;amp;&amp;amp; o2.GetType() == typeof(int))&lt;BR&gt;&amp;nbsp;&amp;nbsp; return ((int)o1) + ((int)o2);&lt;BR&gt;&amp;nbsp;//...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Add takes two objects, so if we utilize the “ldc.i4” instruction to load our ints on to the stack, we’d better box them before calling the Add method. Anyway, the code for the 2 + 4 expression might look like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#000000 size=2&gt;ldc.i4&amp;nbsp; 2.&lt;BR&gt;box&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [mscorlib]System.Int32&lt;BR&gt;ldc.i4&amp;nbsp; 4.&lt;BR&gt;box&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [mscorlib]System.Int32&lt;BR&gt;call&amp;nbsp;&amp;nbsp;&amp;nbsp; object [LateBinder]LateBinder::Add(object, object)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;It seems nasty doesn’t it – firstly, we’re boxing all these ints, and performing a late-bound call to do a simple addition, there goes the perf right? In reality, the Add method (if it’s not virtual) will hopefully be inlined so there’s no method call penalty, and boxing – well, there are tricks you can do to speed that up (have a cache of boxed ints ready to go etc). A lot of these perf tricks are done in the IronPython compiler, so there’s some code to go digging in if one feels like it. &lt;/P&gt;
&lt;P&gt;In fact, there are many optimizations one can do at the dynamic language compiler level to completely remove boxing all together (simple data flow analysis). Some day I’d like to talk about those.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT face=Arial size=4&gt;Language specific types and BCL interop&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;If you’re familiar with Python, you’d have come across a fairly common Python type called a “list”. Lists are defined like so:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;myPythonList = ['hello','world']&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;This is what I call a language specific type, meaning that the language involved has full first class (syntactic and runtime) support for that type and operations on that type. There are many decisions around what that type could look like “under the hood”, a good choice would be to see if it maps safely to an existing BCL type (Dictionary, List&amp;lt;T&amp;gt; etc) so that there is a better chance of that working interoperably with existing BCL libraries (plus, the engineering has already been done for you, so less bugs as a result right?:)). Another possible choice is to cook the type up yourself and place that type in your language runtime. This is the route the IronPython compiler chose, mostly because of common Python libraries that exist for the Python list are not supported by the BCL’s List&amp;lt;T&amp;gt;. The implementation looks like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;namespace IronPython.Objects {&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;public class List : IMutableSequence, IList, IComparable {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int size;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private object[] data;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static List Make() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new List();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void reverse() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Reverse(data, 0, size);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;IronPython has a namespace in its language runtime called “IronPython.Objects”, which contains all the IronPython defined language types (like List) that it has first class support for. You can find these source files in the IronPython source distribution. &lt;/P&gt;
&lt;P&gt;The interesting point to make here about Objects.List is it’s BCL interop capabilities. You’ll notice that List implements IList (and IComparable), meaning anywhere a BCL member takes an IList, this Python List will happily play in that sandpit. One can further ponder the other interesting problems/opportunities available for taking this Python List and making it malleable to other types – like string[]. That way, a Python programmer can pass a BCL member (or other language that produces/consumes) which takes an object[] and Python List. You can achieve this through type marshalling at runtime – probably placing this marshalling code in your languages late-binder.&lt;/P&gt;
&lt;P&gt;Type marshalling is just hard. Look at the COM interop namespaces in the BCL sometime – plenty of gotcha’s hanging around in there. &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT face=Arial size=4&gt;Static to dynamic bindings (event hookup example)&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This long section is some notes on how to get purely static constructs in the type system, binding effectively to dynamic constructs at runtime. I leave it as an exercise to the reader to extrapolate other instances where this may cause headaches for dynamic languages.&lt;/P&gt;
&lt;P&gt;Lets look at an interesting static to dynamic binding problem that dynamic languages face when targeting the CLR. Events, which are basic syntactic sugar for MultiCastDelegates are everywhere in libraries like Winforms – consider the Button.Click event, it has a strongly typed delegate EventHandler:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;public delegate void EventHandler(object sender, EventArgs e);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Now consider the case where you want to subscribe to that event using a “object” based method who’s signature looks like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;.method public static object clickmethod$f0 (object s, object e) cil managed&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The EventHandler delegate signature clearly doesn’t match the method signature – the parameter types don’t match, and the return type has a different type and semantic. That’s not going to stop us of course, so lets dig in to how we can solve this problem. &lt;/P&gt;
&lt;P&gt;First of all, lets look at the way we “subscribe” to events. Take the Button.Click event – subscribing to this in IL looks like the following:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;ldftn&amp;nbsp;&amp;nbsp;&amp;nbsp; instance void MainClass::clickmethod$f0(object, class [mscorlib]System.EventArgs)&lt;BR&gt;newobj&amp;nbsp;&amp;nbsp; instance void [mscorlib]System.EventHandler::.ctor(object, native int)&lt;BR&gt;callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::add_Click(class [mscorlib]System.EventHandler)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;“ldftn” is the IL opcode that loads a function pointer to a method on to the stack. In this case, it loads the function pointer of “clickmethod$f0”. “newobj” then instantiates the EventHandler delegate, passing in the function pointer as an argument (and null or the object instance depending if the method is static or not). Then we call the “add_Click” method, which adds the EventHandler delegate we just created to the Click event. The key thing I’m trying to point out here is – we need to obtain a delegate to the method we wish to invoke.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Enter late-bound delegates.&lt;/EM&gt;&lt;/STRONG&gt; &lt;/P&gt;
&lt;P&gt;The Delegate class has a whole bunch of “CreateDelegate” method overloads, purely for the sole purpose of creating delegates late-bound – excellent for cases like this where the expression of an event hookup looks something like:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Button.Click += clickmethod&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;and resolution of “button.Click” and “clickmethod” must be done at runtime. Okay, so the language runtime resolves “button.Click” to a Reflection based EventInfo, then it resolves clickmethod, which is a method to a Reflection based MethodInfo, and it needs to now cook up a delegate that the “button.Click” event likes. If the “clickmethod” method signature matches the “.Click” event signature perfectly, then a quick call like this: &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Delegate d = Delegate.CreateDelegate(eventInfo.EventHandlerType, clickmethodMethodInfo);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;is all that’s needed. That method call hands you back a delegate, then you can bind that to the event like so:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;eventInfo.AddEventHandler(null, d);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Of course, this will work fine for the case where the EventHandlerType (delegate signature) matches that of the clickmethod method signature. But by looking up at the signatures, you realize they don’t match. What’s the story? &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Co and contravariant (or relaxed) delegate support in Whidbey&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Binding “void EventHandler(object sender, EventArgs e)” to “object clickmethod$f0(object s, object e)” does not exactly match. In Everett, if you tried binding these two guys together, we would throw an exception in your face. In Whidbey, we now allow contravariant parameter bindings, and covariant return parameter bindings. That means, you can be less type specific on the parameters, and more type specific on the return parameter.&lt;/P&gt;
&lt;P&gt;Well, we hit almost all of them: clearly “object sender” matches “object s” exactly, and “object s” is less specific than “EventArgs e”, so we’re fine on the parameters, but we fail on the return type. “void” (a strange type in itself) is not more specific than object (in fact, it’s like apples and oranges here – this basically specifies a whole different calling convention). How would a dynamic language create a delegate to methods that always return object (even though in their implementation, they may not actually return anything)? &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Enter LCG for mismatch delegate hookup&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;I love the new feature Lightweight Code Generation. I talk about it here (&lt;a href="http://blogs.msdn.com/joelpob/archive/2004/03/31/105282.aspx"&gt;http://blogs.msdn.com/joelpob/archive/2004/03/31/105282.aspx&lt;/A&gt;) and here (&lt;a href="http://blogs.msdn.com/joelpob/archive/2004/04/01/105862.aspx"&gt;http://blogs.msdn.com/joelpob/archive/2004/04/01/105862.aspx&lt;/A&gt;). We can essentially generate a method that has the exact signature of the “Click” delegate, do whatever argument shuffling/coercion we need before calling the “clickmethod$f0” method, shuffling return arguments if needed as well, then create a delegate over the LCG method which we can now bind to the event. Cool huh? &lt;/P&gt;
&lt;P&gt;The code to create this LCG method based on the signature of the event (which would probably live in the LateBinder) could look something like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Type delegateReturnType = eventInfo.EventHandlerType.GetMethod("Invoke").ReturnParameter.ParameterType;&lt;BR&gt;ParameterInfo[] delegateParameters = eventInfo.EventHandlerType.GetMethod("Invoke").GetParameters();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Type[] dmHookupParameters = new Type[delegateParameters.Length];&lt;BR&gt;for (int i = 0;i&amp;lt;delegateParameters.Length;i++)&lt;BR&gt;&amp;nbsp; dmHookupParameters[i] = delegateParameters[i].ParameterType;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;DynamicMethod eventHookupMethod = new DynamicMethod("eventHookup", delegateReturnType, dmHookupParameters, typeof(object));&lt;BR&gt;ILGenerator eventIL = eventHookupMethod.GetILGenerator();&lt;BR&gt;//...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Now we need to generate IL that can push the arguments on to the stack, ready for the call. Now, if your dynamic language has special rules around calling convention (type coercion rules etc), why not just make the LCG method call your LateBinder.Call() method so the heavy lifting is done all in one place? That’s exactly what this IL does:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;// emit the call to "LateBinder.Call(object name, object[] args)"&lt;BR&gt;eventIL.Emit(OpCodes.Ldstr, "clickmethod$f0");&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;LocalBuilder local = eventIL.DeclareLocal(typeof(object[]));&lt;BR&gt;eventIL.Emit(OpCodes.Ldc_I4, delegateParameters.Length);&lt;BR&gt;eventIL.Emit(OpCodes.Newarr, typeof(object));&lt;BR&gt;eventIL.Emit(OpCodes.Stloc, local);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;for (int i = 0; i &amp;lt; delegateParameters.Length; i++)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; eventIL.Emit(OpCodes.Ldloc, local);&lt;BR&gt;&amp;nbsp; eventIL.Emit(OpCodes.Ldc_I4, i);&lt;BR&gt;&amp;nbsp; eventIL.Emit(OpCodes.Ldarg, i);&lt;BR&gt;&amp;nbsp; eventIL.Emit(OpCodes.Stelem_Ref);&lt;BR&gt;}&lt;BR&gt;eventIL.Emit(OpCodes.Ldloc, local);&lt;BR&gt;eventIL.Emit(OpCodes.Call, typeof(LateBinder).GetMethod("Call"));&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;(Yes I did deviate from my previous LateBinder example. Just imagine that this LateBinder.Call method does a string based lookup for a MethodInfo, then does an invoke… *grin*)&lt;/P&gt;
&lt;P&gt;Now the interesting part. The IL sequence to basically pop off that result from LateBinder.Call if the delegate return type is typed as void, or cast the “object” return from the LateBinder.Call method to the return type of the delegate.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;if (delegateReturnType == typeof(void))&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; eventIL.Emit(OpCodes.Pop);&lt;BR&gt;&amp;nbsp; eventIL.Emit(OpCodes.Ret);&lt;BR&gt;}&lt;BR&gt;else&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; eventIL.Emit(OpCodes.Castclass, delegateReturnType);&lt;BR&gt;&amp;nbsp; eventIL.Emit(OpCodes.Ret);&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Last but not least, create the delegate to the LCG method:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Delegate d = eventHookupMethod.CreateDelegate(eventInfo.EventHandlerType);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Hook it up to the event:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;eventInfo.AddEventHandler(null, d);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;And we’re done. We’ve created a delegate with a signature that matches the event latebound, hooked it up to an LCG method that does whatever shuffling required and then invokes our LateBinder.Call method to actually call the method we want to call. Very cool huh?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=4&gt;&lt;STRONG&gt;Last but not least…&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;That’s me done for this post. I’ve got a whole bunch more I want to talk about in this space, but I’ll keep that for another day. I’m going to be at the PDC (and Jim Hugunin (&lt;a href="http://blogs.msdn.com/hugunin/"&gt;http://blogs.msdn.com/hugunin/&lt;/A&gt;) should hopefully be there), so if you’re going to be there and you’re interested in learning/discussing more, drop me an e-mail. &lt;/P&gt;
&lt;P&gt;Thanks&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=434728" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>CLR Generics and code sharing</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/11/17/259224.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/11/17/259224.aspx</id><published>2004-11-17T23:02:00Z</published><updated>2004-11-17T23:02:00Z</updated><content type="html">&lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;It’s been a while since I’ve posted - we’ve been busy getting Beta 2 ready, and that means fixing bugs, bugs, and more bugs. I have a bunch of nearly complete posts, mostly around Reflection and type system identity, which I’ll be kicking out soon I hope. Lately, I’ve received a few questions around code sharing on generic methods. I figured this would be as good a forum as any to drill down on some of the details. This post is a bit all over the place, so please post any questions you have below!&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;First up - the high level bits for generics and code sharing:&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; tab-stops: list .5in; mso-list: l0 level1 lfo1"&gt;&lt;span style="mso-list: Ignore"&gt;-&lt;span style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;We do a mix and match of code sharing and specialization, depending what type arguments we’re dealing with. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; tab-stops: list .5in; mso-list: l0 level1 lfo1"&gt;&lt;span style="mso-list: Ignore"&gt;-&lt;span style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;Generic method instantiation code sharing is done for reference type arguments.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; tab-stops: list .5in; mso-list: l0 level1 lfo1"&gt;&lt;span style="COLOR: black"&gt;&lt;span style="mso-list: Ignore"&gt;-&lt;span style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: black"&gt;Generic method specialization is always done for primitives and valuetypes, including enums.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="COLOR: #ff6600"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="COLOR: black"&gt;&lt;strong&gt;What is code sharing again?&lt;o:p&gt;&lt;/o:p&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;u&gt;&lt;span style="COLOR: black"&gt;&lt;o:p&gt;&lt;span style="TEXT-DECORATION: none"&gt;&lt;/span&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="COLOR: black"&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="COLOR: black"&gt;In the case of generics, code sharing is when two or more “compatible” method instantiations point to the same x86 code. An example of this is Foo.M&amp;lt;MyClass1&amp;gt; and Foo.M&amp;lt;MyClass2&amp;gt; sharing the same generated x86, where MyClass1 and MyClass2 are ref types.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="COLOR: black"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="COLOR: black"&gt;Brief history – we also code share for the arrays of reference types in v1.0 and v1.1 (we just use the code for object array).&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;u&gt;&lt;o:p&gt;&lt;span style="TEXT-DECORATION: none"&gt;&lt;/span&gt;&lt;/o:p&gt;&lt;/u&gt;&lt;/i&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;u&gt;&lt;/u&gt;&lt;/i&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;Very quick recap of EE data structures&lt;o:p&gt;&lt;/o:p&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;u&gt;&lt;o:p&gt;&lt;span style="TEXT-DECORATION: none"&gt;&lt;/span&gt;&lt;/o:p&gt;&lt;/u&gt;&lt;/i&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;There’s excellent explanation’s on the CLR’s execution engine data structures in the SSCLI Essentials book. A quick recap though: &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;All objects on the heap have a fixed size pointer that points to a MethodTable, which describes the objects type identity (you get essentially get a managed code representation through RuntimeTypeHandle). MethodTable’s contain pointers to EE structures, and more importantly, a list of the type’s methods and their representative code pointers. These pointers can either be pointing at x86 code, or the JIT stub (which invokes the JIT if a method has not been JIT’ed yet). MethodTable’s are used extensively for type identity.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;MethodDesc’s are small structures used to describe methods. Each method has a representative MethodDesc structure, although it’s not typically used by the runtime unless you’re trying to do bind to methods late-bound (reflection). There are different types of MethodDesc’s in the runtime, but for the purpose of this post, we just assume they’re all basically the same.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Calls on a instance method conceptually look something like this: start with the this pointer, hit the MethodTable, index to the code pointer of the method, then call the code pointer, passing the “this” address as an argument as per x86 calling convention. Calls on static methods do essentially the same thing, just without the “this” pointer being passed as an argument. Of course, the JIT can generate code for direct calls to these various pointers – it does the heavy lifting of MethodTable lookups for code pointers at JIT time.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;u&gt;&lt;/u&gt;&lt;/i&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;Generic Methods in IL&lt;o:p&gt;&lt;/o:p&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;When we introduce generics in to the picture, we have this potential unknown – when we JIT compile, what do we do with locals/arguments of T? How do we generate x86 for something like that? &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Let’s consider the following code snippet: &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;class&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt; Foo&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[MethodImpl(MethodImplOptions.NoInlining)]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;void&lt;/span&gt; M1&amp;lt;T&amp;gt;() &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine(&lt;span style="COLOR: blue"&gt;typeof&lt;/span&gt;(T));&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;Foo f1 = &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; Foo().M1&amp;lt;&lt;span style="COLOR: blue"&gt;string&lt;/span&gt;&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;Foo f2 = &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; Foo().M1&amp;lt;&lt;span style="COLOR: blue"&gt;object&lt;/span&gt;&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;How do we represent the code in M1&amp;lt;T&amp;gt; in IL when we don’t know what T will be? We actually specify the type parameter as “!!arity”, where arity is the index in to the type parameters on the generic method (0 being the first, 1 being the second etc). &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;The Foo.M1&amp;lt;T&amp;gt;() IL code looks like the following: &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;// IL Code for Foo.M1&amp;lt;T&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;.method &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; hidebysig instance &lt;span style="COLOR: blue"&gt;void&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;M1&amp;lt;([mscorlib]System.Object) T&amp;gt;() cil managed noinlining&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;// Code size&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;17 (0x11)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;.maxstack&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;8&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;IL_0000:&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;ldtoken&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;!!0&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;IL_0005:&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;call&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;class&lt;/span&gt; [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;IL_000a:&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;call&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;void&lt;/span&gt; [mscorlib]System.Console::WriteLine(&lt;span style="COLOR: blue"&gt;object&lt;/span&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;IL_000f:&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;nop&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;IL_0010:&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;ret&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;} &lt;span style="COLOR: green"&gt;// end of method Foo::M1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;We make no assumptions about the type that the method will be passed. You can imagine, in the abstract machine world, that calling this method, we would simply replace the !!0 with string or object, depending what was passed in as the generic argument. This imaginary scenario is close to what actually happens when we JIT compile this piece of code. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;Enter: generic methods and code sharing&lt;o:p&gt;&lt;/o:p&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Looking at the code, I have two instances of the same type Foo, calling essentially different methods (ie: M1&amp;lt;object&amp;gt; is not the same as M1&amp;lt;string&amp;gt;, which is also exposed and represented via reflection). Code sharing steps in, these two method instantiations end up pointing to the same x86 code.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;It happens like this: When we hit this piece of code: Foo f1 = &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; Foo().M1&amp;lt;&lt;span style="COLOR: blue"&gt;string&lt;/span&gt;&amp;gt;(), kick the JIT to go compile the method for the first time. We take the IL above, and in a basic sense, replace !!0 with a pointer that calls in to the runtime to get the type information about the type we passed as generic argument in slot 0. Where do we get this pointer from? Well, the magic comes from the calling convention: we supply a “hidden” argument in the call, which is a pointer in to a runtime data structure that supplies us with that information. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;Bring in the “hidden” argument data structure&lt;o:p&gt;&lt;/o:p&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;A pointer to what? Well, in this specific instance where we only need to know about the type argument supplied to the generic method, we create and pass in a MethodDesc pointer for that particular declaration of the method. For the Foo().M1&amp;lt;string&amp;gt; case we pass in a MethodDesc that describes the method as M1&amp;lt;string&amp;gt;, for Foo().M1&amp;lt;object&amp;gt;, we pass in the MethodDesc for M1&amp;lt;object&amp;gt;. The MethodDesc essentially contains all the information needed to describe what !!0 will be. The JIT compiles x86 code to pull the type information out of the MethodDesc pointer.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;So, for the case above, the JIT hits the “ldtoken !!0”, and compiles x86 code to retrieve the type token from the hidden argument pointer which was passed in. This code works for both the string and object case, because we’re hitting a pointer indirection, not a specific piece of code for string or object.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;Cases where we need this “hidden” argument&lt;o:p&gt;&lt;/o:p&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;We generally need this hidden argument for cases where we can’t derive the type information from any means available at x86 execution time in the current stack frame. Below lists a few examples, along with the data structure the hidden argument represents&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;ol style="MARGIN-TOP: 0in" type="1"&gt; &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo2"&gt;Foo&amp;lt;T&amp;gt; static M()&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;== TypeHandle &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo2"&gt;Foo&amp;lt;T&amp;gt; static M&amp;lt;T&amp;gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;== MethodDesc &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo2"&gt;Foo M&amp;lt;T&amp;gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;== MethodDesc &lt;li class="MsoNormal" style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo2"&gt;Foo static M&amp;lt;T&amp;gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;== MethodDesc&lt;/li&gt;&lt;/ol&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; tab-stops: list .5in; mso-list: l1 level1 lfo2"&gt;Number 4 is an interesting one – we actually need both the TypeHandle and the MethodDesc, but the JIT knows that we can generate code to get at the TypeHandle _from_ the MethodDesc (there’s an indirection there, which I think is described in SSCLI Essentials). &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;One case that’s not pointed out is Foo&amp;lt;T&amp;gt; M(). Because M is an instance method, and we already pass in the “this” pointer as per the calling convention, we can derive the type argument of type argument T, directly from the “this” pointer. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;For those that ask the question – why pass in the MethodDesc/TypeHandle, why can’t we just pass in the type handle as a “hidden argument”. Good question, but for the case where we have more than one generic parameter, it makes sense to minimize the amount of arguments passed in at calling convention time. M&amp;lt;U,W,Z&amp;gt; for example, is fully described by the MethodDesc, so its easier and more efficient to pass in just the MD pointer and generate code to index in to the MethodDesc appropriately.&lt;i style="mso-bidi-font-style: normal"&gt;&lt;u&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/u&gt;&lt;/i&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;Okay, so why the lack of code sharing on primitives and value types?&lt;o:p&gt;&lt;/o:p&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;While technically, we could code share on primitives and value types, it’s clearly not very efficient to do so. Just to make it more understandable: &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Consider: &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Foo { M&amp;lt;T&amp;gt;() {} }&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;new Foo().M&amp;lt;int&amp;gt;();&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;new Foo().M&amp;lt;double&amp;gt;();&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;The JIT will actually go off and generate two separate code sections for both of those instantiations. Why? Well, primitives and valuetypes live on the stack and have no reference to a MethodTable (unless they’re boxed). Generally, different valuetypes/primitives have different data sizes, int and double being a good example of that. The JIT clearly can’t generate x86 code that deals with unknown data sizes, so it specializes them. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;The runtime could have made these primitive/valuetype guys play well with code sharing by boxing every time we call, but isn’t preventing unnecessary boxing one of the best reasons around for using generics? &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;Partial specialization&lt;o:p&gt;&lt;/o:p&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;I’m not exactly sure if we the CLR team calls it partial specialization, but that’s what I’ll call it for this blog post &amp;lt;g&amp;gt;. For cases where we have a valuetype and a ref type, we specialize for the valuetype case, and link the sharable code for the ref type. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Foo&amp;lt;int&amp;gt;.M&amp;lt;string&amp;gt; and Foo&amp;lt;int&amp;gt;.M&amp;lt;object&amp;gt; are essentially the same code. We share M&amp;lt;T&amp;gt; in the context of Foo&amp;lt;int&amp;gt;. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;More resources&lt;o:p&gt;&lt;/o:p&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Some of this is fairly dense; the blog posts intention is for Google to pick some of this up, so I can remember how it works. If you want to know more detail about this, check out the following: &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;a href="http://research.microsoft.com/projects/clrgen/"&gt;http://research.microsoft.com/projects/clrgen/&lt;/a&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;a href="http://research.microsoft.com/projects/clrgen/generics.pdf"&gt;http://research.microsoft.com/projects/clrgen/generics.pdf&lt;/a&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/csharp_generics.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/csharp_generics.asp&lt;/a&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;The book I mention: Shared Source CLI Essentials, 2003, ISBN: 059600351X&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;That’s all for now – hopefully I’ll have more time in the coming weeks to jot down some more random brain dump stuff from inside the guts of the CLR. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=259224" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>CLR Metadata – please sir, let me consume the bits…</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/09/22/233121.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/09/22/233121.aspx</id><published>2004-09-23T00:36:00Z</published><updated>2004-09-23T00:36:00Z</updated><content type="html">&lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Firstly, the &lt;a href="http://www.razorsoft.net/images/ChrisBigMetadataDiagram.vsd"&gt;big metadata diagram&lt;/a&gt;. Thanks to Chris King for this absolute&amp;nbsp;gem. Now, on to the various ways developers can read and write metadata bits...&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;Unmanaged Metadata Reader API’s&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;I mentioned various times before that there exists Unmanaged Metadata reader/writer APIs that you can use to traverse and write out metadata structures with. It’s a great workaround for those subtle Reflection (or Reflection.Emit) bugs, or gaping holes in the Reflection API. I get a few questions here and there regarding these unmanaged API’s (mostly bootstrapping related questions), so I’ve decided to drop in documentation and a bit of source code I cooked up today:&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Some documentation for the Unmanaged Metadata API’s &lt;a href="http://blog.monstuff.com/archives/images/Metadata_Umanaged_API.pdf"&gt;can be found here&lt;/a&gt;, (also on google, MSDN and various newsgroups). &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;A quick bootstrap code snippet is below, which gets all method names for all type definitions in a given assembly:&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;:/&amp;gt; MDRExample.exe System.Web.dll&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;// MDRExample.cpp : Defines the entry point for the console application.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;//&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;#include&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="COLOR: maroon"&gt;"stdafx.h"&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;#include&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="COLOR: maroon"&gt;"cor.h"&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;#include&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="COLOR: maroon"&gt;&amp;lt;stdio.h&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;#include&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="COLOR: maroon"&gt;&amp;lt;objbase.h&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;int&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; _tmain(&lt;span style="COLOR: blue"&gt;int&lt;/span&gt; argc, _TCHAR* argv[])&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;{ &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;IMetaDataDispenser* _IMetaDataDispenser;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;IMetaDataImport* _IMetaDataImport;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;IMetaDataAssemblyImport* _IMetaDataAssemblyImport;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CoInitialize( 0 );&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;HRESULT hr;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;// go create all the interfaces&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = CoCreateInstance(CLSID_CorMetaDataDispenser, 0,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CLSCTX_INPROC_SERVER,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;IID_IMetaDataDispenser,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(LPVOID*)&amp;amp;_IMetaDataDispenser );&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt; ( FAILED(hr) )&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;throw&lt;/span&gt; &lt;span style="COLOR: maroon"&gt;"failed on IMetaDataDispenser"&lt;/span&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;wchar_t&lt;/span&gt; _FileName[MAX_PATH];&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mbstowcs( _FileName, argv[1], lstrlen(argv[1])+1 );&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = _IMetaDataDispenser-&amp;gt;OpenScope(_FileName, ofRead,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;IID_IMetaDataImport,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(LPUNKNOWN *)&amp;amp;_IMetaDataImport );&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt; ( FAILED(hr) )&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;throw&lt;/span&gt; &lt;span style="COLOR: maroon"&gt;"failed on IMetaDataImport"&lt;/span&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = _IMetaDataDispenser-&amp;gt;OpenScope(_FileName, ofRead,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;IID_IMetaDataAssemblyImport,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(LPUNKNOWN *)&amp;amp;_IMetaDataAssemblyImport);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt; ( FAILED(hr) )&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;throw&lt;/span&gt; &lt;span style="COLOR: maroon"&gt;"failed on IMetaDataAssemblyImport"&lt;/span&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;HCORENUM&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_hCorEnum = 0;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mdTypeDef&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_typeDefs[2048];&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ULONG&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_countTypeDefs = &lt;span style="COLOR: blue"&gt;sizeof&lt;/span&gt;(_typeDefs);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;// go get all the type defs defined in the assembly&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = _IMetaDataImport-&amp;gt;EnumTypeDefs(&amp;amp;_hCorEnum, &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_typeDefs, &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_countTypeDefs, &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;amp;_countTypeDefs);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;for&lt;/span&gt; (&lt;span style="COLOR: blue"&gt;int&lt;/span&gt; i=0;i&amp;lt;_countTypeDefs;i++)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mdMethodDef _methodDefs[2048];&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ULONG _countMethodDefs = &lt;span style="COLOR: blue"&gt;sizeof&lt;/span&gt;(_methodDefs);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;// go get all the methods defined on the typedef&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_hCorEnum = 0;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = _IMetaDataImport-&amp;gt;EnumMethods(&amp;amp;_hCorEnum, &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_typeDefs[i], &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_methodDefs, &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_countMethodDefs, &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;amp;_countMethodDefs);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;// now print out the methods name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;wchar_t&lt;/span&gt; _methodName[1024];&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ULONG _countMethodName = &lt;span style="COLOR: blue"&gt;sizeof&lt;/span&gt;(_methodName);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;for&lt;/span&gt; (&lt;span style="COLOR: blue"&gt;int&lt;/span&gt; j=0;j&amp;lt;_countMethodDefs;j++)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;wchar_t&lt;/span&gt; _methodName[1024];&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = _IMetaDataImport-&amp;gt;GetMethodProps(_methodDefs[j], 0, _methodName, _countMethodName, &amp;amp;_countMethodName, 0, 0, 0, 0, 0);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;wprintf(_methodName);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;printf(&lt;span style="COLOR: maroon"&gt;"\n"&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;return&lt;/span&gt; 0;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;AbsIL (Abstract IL)&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;AbsIL is a toolkit from the smart people (yeah that’s you &lt;a href="http://research.microsoft.com/~dsyme/"&gt;Don&lt;/a&gt;) at &lt;a href="http://research.microsoft.com/"&gt;Microsoft Research&lt;/a&gt;, that provides an abstracted view of metadata (generally in the form of an abstract syntax tree). Of course, having this transformation from metadata relationships to an abstract tree view gives you all sorts of opportunity to do your little bit of analysis/manipulation. Some interesting uses may include things like assembly re-writing, contract and performance analysis, discovery for plug-in like architectures, exception handling related issues and more. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Consumers of this toolkit beware – you’ll need to brush up on &lt;a href="http://caml.inria.fr/ocaml/htmlman/"&gt;OCaml&lt;/a&gt;, as the AbsIL libs have been written in &lt;a href="http://research.microsoft.com/projects/ilx/fsharp.aspx"&gt;F#&lt;/a&gt; (therefore exposing this functionally). Writing an AbsIL program in C# can be very frustrating to begin with, but sometimes power comes with pain. Here’s something I hacked up in C# that’s similar to the Unmanaged Metadata reader example above – it prints the name of each type and method to the screen from an assembly provided as a command line argument:&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt; System;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;class&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt; AbsILExample&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;static&lt;/span&gt; &lt;span style="COLOR: blue"&gt;object&lt;/span&gt; writeName(&lt;span style="COLOR: blue"&gt;object&lt;/span&gt; t) &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{ &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (t &lt;span style="COLOR: blue"&gt;is&lt;/span&gt; Il.type_def)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine(((Il.type_def) t).tdName); &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;else&lt;/span&gt; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (t &lt;span style="COLOR: blue"&gt;is&lt;/span&gt; Il.method_def)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine(((Il.method_def) t).mdName);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;return&lt;/span&gt; t;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;static&lt;/span&gt; &lt;span style="COLOR: blue"&gt;object&lt;/span&gt; writeMethodName(&lt;span style="COLOR: blue"&gt;object&lt;/span&gt; t) { List.iter(&lt;span style="COLOR: blue"&gt;new&lt;/span&gt; System.Func(writeName), Il.dest_mdefs(((Il.type_def)t).tdMethodDefs)); &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; t; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;static&lt;/span&gt; &lt;span style="COLOR: blue"&gt;void&lt;/span&gt; &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:place w:st="on"&gt;Main&lt;/st1:place&gt;(&lt;span style="COLOR: blue"&gt;string&lt;/span&gt;[] args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Il.modul module = Ilread.read_binary(args[0], FS.option.MkNone());&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;FS.list l = Il.dest_tdefs(module.modulTypeDefs);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine("type names:");&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;List.iter(&lt;span style="COLOR: blue"&gt;new&lt;/span&gt; System.Func(writeName), l);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine("\nmethod names:");&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;List.iter(&lt;span style="COLOR: blue"&gt;new&lt;/span&gt; System.Func(writeMethodName), l);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;a href="http://research.microsoft.com/projects/ilx/absil.aspx"&gt;Find AbsIL at the Microsoft Research website&lt;/a&gt;.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;PEAPI (or Perrrwapi)&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;a href="http://www.citi.qut.edu.au/research/plas/index.jsp"&gt;My old research lab&lt;/a&gt; has a managed metadata reader/writer called PEAPI. From the website it looks like they’ve kicked some butt on perf (“The new backend can create a program executable file in almost exactly the same length of time as it takes to write the equivalent CIL text file”). Crazy fast. I believe the Mono C# compiler uses this component as its code generator, although I can’t verify that. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;I don’t have much experience with this API, I haven’t had a chance to write some stuff with the latest bits, although I do remember years back when the component author spat out the first alpha - fun stuff. Ahh the good old days…&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;a href="http://www.citi.qut.edu.au/research/plas/projects/cp_files/cpnet.html"&gt;Find it here. &lt;/a&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;IL Reader for .NET&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;A fellow Microsoftee, Lutz Roeder wrote a great .NET library for IL reading called IL Reader. While it doesn’t exist for 2.0 (not exactly sure what his plans are for a 2.0 rev), it supports reading a types methods in 1.0 and 1.1 assemblies. The great thing about this library is that it returns its instructions as Reflection.Emit opcodes, giving you the ability to read in, manipulate, and write out via Reflection.Emit with relative ease. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Find IL Reader here&lt;/a&gt;. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;Whidbey’s MethodBody API&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;I mention this API &lt;A href="http://blogs.msdn.com/joelpob/archive/2004/06/22/163206.aspx"&gt;here&lt;/a&gt; and &lt;A href="http://blogs.msdn.com/joelpob/archive/2003/12/18/53745.aspx"&gt;here&lt;/a&gt;. Similar to Lutz’s IL Reader, but doesn’t have the complete opcode abstraction yet. You’ll have to take a byte stream, go find the ECMA spec or something, and decode the bytes yourself (which is fairly trivial, yet fun to do). &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Feel free to leave comments below if you know of other interesting Metadata reading/writing toolkits - I've only done a quick braindump here. In anycase, hopefully there's some value here in this post for those who want to read and write any metadata bit they like! &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=233121" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>TechEd AU/NZ shoutouts</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/09/22/233117.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/09/22/233117.aspx</id><published>2004-09-23T00:11:00Z</published><updated>2004-09-23T00:11:00Z</updated><content type="html">&lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;2 months since my last post? – Yeah I know, I’ve been very busy lately with Whidbey CLR commitments. I'll have two posts today – a quick postmortem on TechEd AU/NZ, and a post on various metadata related API’s developers are able to consume. They're kind of related... trust me.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;AU/NZ TechEd 2004:&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;I took a trip down under to &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:country-region w:st="on"&gt;Australia&lt;/st1:country-region&gt; and &lt;st1:place w:st="on"&gt;&lt;st1:country-region w:st="on"&gt;New Zealand&lt;/st1:country-region&gt;&lt;/st1:place&gt; for TechED 2004. The event was a great success, and I was very impressed by the colourful array of people I got to chat with – &lt;a href="http://notgartner.com/"&gt;Mitch Denny&lt;/a&gt;, &lt;a href="http://msmvps.com/greglow/"&gt;Greg Low&lt;/a&gt;, &lt;A href="http://blogs.msdn.com/frankarr/"&gt;Frank Arrigo&lt;/a&gt;, my old research pals &lt;a href="http://www.rikware.com/"&gt;Richard&lt;/a&gt; and &lt;a href="http://11011.net/"&gt;Doug&lt;/a&gt;, &lt;a href="http://www.thespoke.net/MyBlog/Bernard/MyBlog.aspx"&gt;Bernard Oh&lt;/a&gt;, &lt;a href="http://www.dotnetperformance.com/"&gt;Nick Wienholt&lt;/a&gt;, Steve Riley, &lt;a href="http://www.stanski.com/"&gt;Peter Stanski&lt;/a&gt; and many more. So much fun hearing what these people work on, and then the heated debates that follow as to why the runtime doesn’t support this and that. I especially enjoyed the geek dinner in &lt;st1:City w:st="on"&gt;&lt;st1:place w:st="on"&gt;Canberra&lt;/st1:place&gt;&lt;/st1:City&gt;, which in traditional aussie style, ended up being a booze up at a local pub.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;It seems that my “CLR Under the hood” talk was the most popular from the two talks I presented. I had a lot of questions afterwards about my metadata slides, which I suspect stems from the various research and third party products that are coming out based on metadata analysis and manipulation. I did promise in the talk to post up the big Visio diagram that I had in one slide that lays out metadata table dependencies, which is why this post has a follow up post on metadata - told you they were related. :)&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;I didn't manage to get any photos from the event, so if an attendee catches this post somehow, and has some photos he/she would like to share, please send them on through, I'd love to see them, and share them with some other CLR folk. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;On to the next post...&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=233117" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>CLR Type System notes</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/07/19/187709.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/07/19/187709.aspx</id><published>2004-07-19T18:49:00Z</published><updated>2004-07-19T18:49:00Z</updated><content type="html">&lt;P&gt;Over the past couple of months, I've&amp;nbsp;written up&amp;nbsp;a bunch of notes surrounding the CLR type system. You'll notice that it's littered with &amp;#8220;This is how Reflection deals with these types&amp;#8220;, as it's ment to be the start of a document that illustrates Reflection&amp;gt;Type system interactions. As always, it's just a brain dump, and you can expect some errors, along with gaping holes in reasoning and information. Feel free to leave a comment if there is a particular part of these notes you'd like me to dig deeper on.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The underlying type system&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Following is a description of the sets of types that are treated specially either by the virtual machine or the internal system. It&amp;#8217;s important to have a good understanding of the characteristics of these sets as they are the key blocks reflection builds on. &lt;/P&gt;
&lt;P&gt;Please refer to the ECMA spec (partition I) for a more formal description of those types. In the next sections we want to outline features that are more interesting from a reflection point of view, so definitions may be slightly different (and certainly less formal) than those presented in the ECMA specification. The idea is to provide a general set of rules that can help people using reflection and/or reflection emit to do type analysis.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;ReferenceType&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Referred to common instances that are naturally allocated on the gc heap (i.e. Object, String). The object pointer points to type information for the instance (a MethodTable). The instance is fully described by the MethodTable. &lt;BR&gt;We use Reference Type here to identify instances that are unambiguosly described by their MethodTable. That is, the instance pointer, points to the exact type information.&lt;/P&gt;
&lt;P&gt;In that respect obtaining the TypeHandle from the instance is &amp;#8220;conceptually&amp;#8221; as simple as dereferencing the instance pointer and provides the full type information for that instance (Type.GetTypehandle(Object)).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;ValueType&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;ValueTypes are types that derive from System.ValueType. They cannot be derived from, so they are implicitly sealed types.ValueTypes have stack semantic; that is, allocation of a ValueType does not occur on the gc heap but rather on the stack. ValueTypes can be moved on the gc heap via boxing (&amp;#8216;box&amp;#8217; IL opcode). A copy of the instance is made onto the gc heap as a result of boxing.&lt;/P&gt;
&lt;P&gt;When on the stack, ValueTypes are not self describing, they do not carry any type information. Usually an object* points to the MethodTable of that object, the type of that instance. That allows to retrieve type information by simply having a reference to an instance. That&amp;nbsp; is not true for ValueTypes when allocated on the stack. A reference to a value type is a pointer to the beginning of the data for that value type.&lt;/P&gt;
&lt;P&gt;In the unboxed form, they are tracked by flow analysis (either the type location of the local or an argument). Type safety is enforced by flow analysis (it&amp;#8217;s referring to a location - local .locals - or argument - which have type information via the Method signature). In their boxed form, they carry their MethodTable and thus are self describing. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;STRONG&gt;Note:&lt;BR&gt;&lt;/STRONG&gt;&lt;/EM&gt;A ValueType derivative is allowed to declare methods of a static or instance nature. Virtual methods are not allowed to be specified on ValueType&amp;#8217;s because for dispatch, the runtime needs the &amp;#8220;this&amp;#8221; pointer. Clearly, because the runtime identifies the ValueType through flow analysis, there is no &amp;#8220;this&amp;#8221; pointer on the stack at the point of invocation. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Primitive (Scalar types)&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Primitives are built-in types that are treated specially by the system. They have special encoding in metadata and they have explicit opcodes that can operate on them (i.e. add opcode for numeric values).&amp;nbsp; There are a set of implicit conversion rules (int to long) applied to them. Reflection implicitly provides conversion of primitives during invocation whenever there is no loss of information. In any other respect primitives have exactly the same semantic as ValueType since they are ValueTypes. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Note:&lt;BR&gt;&lt;/EM&gt;&lt;/STRONG&gt;C# &amp;#8220;int&amp;#8221; and System.Int32 are essentially the same thing, the C# compiler uses the syntactic sugar to minimize syntax overhead. In general, these primitive types are derived from ValueType and perform a set of common operations (CompareTo, Equals, GetHashCode, ToString and various conversion methods).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Enum&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Enums are ValueType as well. However they&amp;#8217;re special because Enum can only wrap a limited set of primitive types. They have somewhat peculiar assignability rules with respect to their underlying types and in that respect it can be important to distinguish them from other ValueTypes or primitives.&lt;/P&gt;
&lt;P&gt;For instance the beahvior of the castclass (or isinst) and unbox instructions over a boxed enum instance is somewhat inconsistent. Consider the following:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;Color c = Color.Black;&lt;BR&gt;Object o = c;&lt;BR&gt;int i;&lt;BR&gt;&lt;/FONT&gt;an IL sequence using classcast will fail to assign to int local i&lt;BR&gt;&lt;FONT color=#0000ff&gt;ldloc o&lt;/FONT&gt; &lt;BR&gt;castclass int32 // this will throw InvalidCastException&lt;BR&gt;&lt;FONT color=#0000ff&gt;stloc i&lt;/FONT&gt;&lt;BR&gt;however an unbox instruction will work just fine&lt;BR&gt;&lt;FONT color=#0000ff&gt;ldloc o&lt;BR&gt;unbox int&lt;BR&gt;ldind.i4&lt;BR&gt;stloc i&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In other words there are valid and verifiable IL sequences that allow a boxed enum instance to be assigned to its underlying type or to a different compatible enum type, whereas other sequences will throw. Considering reflection always deals with boxed value, there is an asymmetry in operations that check type assignability (i.e. binding) versus operation that check instance assignability (i.e. invocation).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Array&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;They are special reference types. Object layout for array is different to normal reference types &amp;#8211; an instance of an array may point to a shared MethodTable. Instances of Object[], String[] they all point to the same MethodTable (Object[]). This is true for all arrays of reference types as they share the same gc layout. For value types the array instance carries the specific MethodTable (i.e int[], EnumColor[], MyStruct[]).&lt;/P&gt;
&lt;P&gt;Arrays are also special in their assignability rules (array covariance). A String[] can be assigned to an Object[] even though Object[] is not in the hierarchy of String[].&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;ByRef&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;ByRef types are managed pointers. ByRef don&amp;#8217;t box and there are very few IL instruction that can be performed on ByRef types (i.e. ldind.ref, stind.ref). Because of that restriction there is never an instance of a ByRef type as far as reflection is concerned. However ByRef types are real, concrete types in the type system. Inspecting a method that takes a ByRef arg will reveal a unique type that is in no relationship with the type it represents (i.e. int&amp;amp; and int are in no relationship).&lt;/P&gt;
&lt;P&gt;Reflection simulates ByRef and it&amp;#8217;s the user responsibility to fetch the updated value out of the argument array used in reflection invocation. Verifiable IL ensures that ByRef types are only used in argument position. Usage of ByRef in any other location (return value, fields) results in unverifiable code.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Note:&lt;BR&gt;&lt;/EM&gt;&lt;/STRONG&gt;Interesting features of ByRef&lt;/P&gt;
&lt;P&gt;ChangeMyString(ref string s)&lt;/P&gt;
&lt;P&gt;How do I discover via Reflection? When Reflection takes it as an argument (new Object[] myref) to late bound invoke a method that takes a reference, Reflection actually passes the object array, the method (invoked latebound) modifies the array reference instead of the actual ByRef variable that we wanted to modify.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;TypedRef&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;They are a special form of ByRef. They are a struct composed of two fields: a ByRef value to a location and a type compatible to the ByRef location. It can specify a contract on a local variable via the locals signature, or can be used for method parameters. TypedRef also share the limitations of ByRef in verifiable code.&lt;/P&gt;
&lt;P&gt;TypedRef could be used by dynamic and latebound languages as a way to tag a location with information that is different from the runtime type of an object. That type information could be used by a language runtime to direct binding. However given the verification limitation we are not aware of any language that uses TypedRef. TypedRef are used in vararg functions and&amp;nbsp; are returned as a result of enumerating over the vararg argument list. The type the TypedRef points to is the statically declared type (as defined by the compiler in the metadata vararg signature).&lt;/P&gt;
&lt;P&gt;There exists C# keywords and methods that hang of TypedReference that specifically deal with creating and manipulating TypedReferences: &lt;/P&gt;&lt;FONT color=#0000ff&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: blue; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;__makeref&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;&lt;FONT color=#000000&gt;(variable):&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN style="COLOR: green"&gt;// Construction of TypedReference&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: blue; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;__reftype&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;&lt;FONT color=#000000&gt;(typedReference)&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN style="COLOR: green"&gt;// Returns the Type that the TypedReference struct holds&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="COLOR: blue; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;__refvalue&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;&lt;FONT color=#000000&gt;(typedReference)&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN style="COLOR: green"&gt;// Changes the value of the &amp;amp;ptr the TypedReference holds&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;&lt;FONT color=#000000&gt;TypedReference.MakeTypedReference()&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;&lt;FONT color=#000000&gt;TypedReference.SetTypedReference()&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;&lt;FONT color=#000000&gt;TypedReference.GetTargetType()&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt"&gt;&lt;FONT color=#000000&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;STRONG&gt;Pointer&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;They represent an unmanaged pointer. Used in unsafe code, the usage of pointers requires skip verification. &lt;BR&gt;Though pointers can box, their type identity is lost when boxing. This is particularly difficult for Reflection that always deals with boxed entities. There is no way to make reflection code that uses pointers type safe. Of course code using pointers is never verifiable by definition, but the system will generally check type safety and do properly binding in the presence of pointers. Reflection is less accurate in that respect .&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;COMObject&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;COMObject are types that are somehow exposed to the system via COM interop.&lt;BR&gt;COMObject may be imported via tlbimp in which case they have some static type information that can be used to reason over them. However in the presence of a COMObject instance assignability is somewhat of a fuzzy concept.&lt;/P&gt;
&lt;P&gt;Because of the semantic of COM, assignability is the result of a IUnknown::QueryInterface() call on that instance and thus may, in principle, give varying results for different instances. When no static type information is available every COM instance will show as an instance of __COMObject and few api will give results that are different from instance to instance (assignability, guid). In that sense type identity is not enough to guarantee assignability. The presence of __COMObject requires logic outside of the type system.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Interface&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Interfaces are very much like Reference Types. However they are special in that they do not specify a concrete type but rather a contract a type must adhere to. Walking an interface hierarchy will not lead to Object even though Interface types are assignable to Object.&amp;nbsp; Deriving from an interface does not require exposing publicly any of the interface&amp;#8217;s methods, however the interface methods must be implemented at least privately by a concrete type.&amp;nbsp; An InterfaceMapping struct is exposed via Reflection to identify the implementation of an interface for a given type.&lt;BR&gt;An interface has a MethodTable (TypeHandle) but it never has an instantiation. Instances never point to an interface MethodTable.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;TransparentProxy&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;A TransparentProxy is a type that acts as a proxy for another type. The TransparentProxy type is never revealed to the user. It&amp;#8217;s an internal type. Every trasparent proxy points to the same MethodTable, the unique representation of the TrasparentProxy type.&amp;nbsp; So without extra operations transparent proxy do not carry any type identity. In that respect dealing with atransparent proxy introduces a perf penalty to type identity in the system. When an instance is asked for its type a check about transparent proxy needs to preceed any other check as, if the object is indeed a transparent proxy, a more complicated dereference needs to happen in order to fetch the &amp;#8220;real&amp;#8221; type of that object.&lt;/P&gt;
&lt;P&gt;There are explicit checks in the runtime to make sure you never get back a TransparentProxy. Inspecting mscorlib metadata will show a __TransparentProxy type, however there is no representation of that type as System.Type. TransparentProxy does not exist in the type system.&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Generic&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Perhaps another time&amp;#8230;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;TypeParameter&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Perhaps another time&amp;#8230;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Delegate&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Normal type analysis over delegate types will work as expected. They are true types in the type system.&lt;BR&gt;However they are special in the way they wrap a function pointer. They were build with the idea of being the verifiable function pointer in the system. There are very special verification rules around deelgate construction. The rules for verification around delegates are extremely tight and bound to a well known IL sequence.&lt;/P&gt;
&lt;P&gt;There are also very special rules in how you define your delegate type inheritance. System.Delegate cannot be derived from directly. Every delegate type must derive from System.MulticastDelegate. The presence of both types is more an artifact of historical evolution of the system than a real need (the clr used to make a distinction between System.Delegate &amp;#8211; single cast delegate &amp;#8211; and System.MulticastDelegate. That distinction, however, is long gone).&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=187709" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>TechED Australia/New Zealand 2004 preperations</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/07/05/173484.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/07/05/173484.aspx</id><published>2004-07-05T22:50:00Z</published><updated>2004-07-05T22:50:00Z</updated><content type="html">&lt;P&gt;Looks like I'll be taking the long flight down to &lt;A href="http://www.microsoft.com/nz/teched/"&gt;Auckland, NZ&lt;/A&gt; and &lt;A href="http://www.microsoft.com/australia/events/teched2004/default.aspx"&gt;Canberra Australia&lt;/A&gt; to speak at TechEd 2004 under the developer tools banner. This week, I'll start the speaking preperations -&amp;nbsp;I suspect&amp;nbsp;it will take me around three weeks to perfect the two talks I'll be delivering (both CLR centric).&amp;nbsp;I find all of this pretty exciting - I get to travel home for a week AND get to talk about the nuts and bolts of what&amp;nbsp;we're working on.&lt;/P&gt;
&lt;P&gt;Feel free to get in &lt;A href="http://blogs.msdn.com/joelpob/contact.aspx"&gt;contact&lt;/A&gt;&amp;nbsp;if you're going to be in town and want to shoot the breeze about Rotor, CLR, languages or &lt;A href="http://www.microsoft.com/"&gt;the big house&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=173484" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>What's new in System.Reflection (and friends)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/06/22/163206.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/06/22/163206.aspx</id><published>2004-06-23T05:21:00Z</published><updated>2004-06-23T05:21:00Z</updated><content type="html">&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Figured I'd take the opportunity to capitalize on the increased link traffic Brad sent my way, by giving a quick and dirty overview of &amp;#8220;What&amp;#8217;s new in Reflection&amp;#8221;. Illustrated are features I believe are worth their weight in gold - it's a subset of the overall change list. I wrote some of this a little while back to be included in the Whidbey docs, not sure if they&amp;#8217;ve made it there yet. As always, things can and normally do change, and taking dependencies on Beta bits is generally a &amp;#8220;bad thing(tm)&amp;#8221;. Nevertheless, here goes:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="mso-bookmark: _Toc74986877"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="mso-bookmark: _Toc74986877"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Lightweight code gen (LCG)&lt;/B&gt;&lt;/SPAN&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;LCG is probably one of the most interesting features in the late-bound space. I&amp;#8217;ve spoken briefly about it &lt;A href="http://blogs.msdn.com/joelpob/archive/2004/03/31/105282.aspx"&gt;here&lt;/A&gt; and &lt;A href="http://blogs.msdn.com/joelpob/archive/2004/04/01/105862.aspx"&gt;here&lt;/A&gt;. Provides enhanced runtime code generation facilities for emitting static methods at runtime. Less overhead (no need to generate assemblies, modules and types at runtime). GC collection of generated methods which means better resource utilization in long running applications. LCG also has the ability to skip JIT-time visibility checks.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;ReflectionOnly context&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;A new feature in Whidbey that allows the user to load an assembly in the &amp;#8220;ReflectionOnly&amp;#8221; loader context, &lt;B style="mso-bidi-font-weight: normal"&gt;where no code will be executed&lt;/B&gt;. This allows for some loader restrictions to be relaxed, such as the applying of policy. It also allows for reflection over architecture specific assemblies (Reflection over 64bit generated assemblies from a 32bit environment). A example subset of the API:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Assembly&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; asm = &lt;B&gt;&lt;SPAN style="COLOR: navy"&gt;Assembly&lt;/SPAN&gt;&lt;/B&gt;.ReflectionOnlyLoad("assembly.dll");&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;// ...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Type&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; t = &lt;B&gt;&lt;SPAN style="COLOR: navy"&gt;Type&lt;/SPAN&gt;&lt;/B&gt;.ReflectionOnlyGetType("MyType", &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;);&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Reflection over MethodBody&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;This new Whidbey feature allows a user to reflect over a given methods IL stream, its locals, and its exceptions. This is a preliminary API for the power users of reflection. It basically gives the user the ability to parse an IL byte stream. A user is able to reflect on underlying method metadata, and make rational decisions about methods based on their functionality, code paths, exception handling and usage. It also allows a user to realize more than just the method contract and signature. An example subset of the API:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;MethodInfo&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt; mi = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(Foo).GetMethod("Bar");&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;MethodBody&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt; mb = mi.GetMethodBody();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;Console&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;.WriteLine("MaxStackSize: " + mb.MaxStackSize);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;Console&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;.WriteLine("Local Signature metadata token: " + mb.LocalSignatureMetadataToken);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;Console&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;.WriteLine("Byte array length: " + mb.GetILAsByteArray().Length);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;Console&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;.WriteLine("Byte array: " + System.Text.&lt;SPAN style="COLOR: navy"&gt;Encoding&lt;/SPAN&gt;.ASCII.GetString(mb.GetILAsByteArray()));&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;// ...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Token Handle Resolution API&amp;#8217;s&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;My favorite. We&amp;#8217;ve got some work to do here, but more on that later. New API&amp;#8217;s added to move from Info to metadata token and RuntimeHandle. New API&amp;#8217;s added to move from metadata token to RuntimeHandle. User is able to burn in type identity using the Module and metadata token. This has some fairly complex performance and working set benefits that I hope to blog about some other day. There's also the general sense of a better late-bound experience with runtime identity.&amp;nbsp;Also has some interesting &amp;#8220;if you were to build a compiler&amp;#8221; implications. Example subset of the API:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;int&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; fooToken = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(Foo).MetadataToken;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;RuntimeTypeHandle&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; typeHandle = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(Foo).Module.ModuleHandle.ResolveTypeHandle(fooToken);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;// ...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Reflection and Reflection.Emit support for Generic types&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I think this has been well blogged about. We support full reflection and code generation on and of generics types. Various API&amp;#8217;s have been added to the XXXInfo range of API&amp;#8217;s, along with added Reflection.Emit API&amp;#8217;s. I don&amp;#8217;t believe the latest community drop supports full Reflection.Emit generics support, but expect that for Beta 2. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Improved Reflection support for Custom Attributes&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;We can now return a class that has information about a custom attribute, but yet does not execute its constructor! This is part of the whole &amp;#8220;ReflectionOnly&amp;#8221; story, and generally gives some important semantic benefits. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Improved Performance&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Touchy subject. I&amp;#8217;ll move on before I get in trouble&amp;#8230; ;)&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Writing a tool (using Reflection of course) to do a diff over &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:place w:st="on"&gt;&lt;st1:City w:st="on"&gt;Everett&lt;/st1:City&gt;&lt;/st1:place&gt; vs Whidbey API&amp;#8217;s is generally how I work out what we&amp;#8217;ve added in other namespaces. It&amp;#8217;s pretty simple to do, so I&amp;#8217;ll leave it as an exercise to the reader.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Enjoy. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=163206" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>Rotor (SSCLI) Servicing updates - Windows XP SP2 fix included</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/06/21/162105.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/06/21/162105.aspx</id><published>2004-06-22T06:19:00Z</published><updated>2004-06-22T06:19:00Z</updated><content type="html">&lt;P&gt;Jan Kotas, a developer on the CLR team, and an original member of the Rotor team has recently started a &lt;A href="http://servicing.sscli.net/"&gt;servicing project&lt;/A&gt; for the V1 source. This fixes a few known issues, and for the interest of google indexing, fixes one issue in particular that many will eventually run into: Windows XP SP2 Rotor build bug. It also includes fixes to support the building and running of Rotor V1 on the following OS's: &lt;/P&gt;
&lt;P&gt;- Windows Server 2003&lt;BR&gt;- Mac OSX 10.3&lt;BR&gt;- FreeBSD 5.2 &lt;BR&gt;- Windows XP SP2&lt;/P&gt;
&lt;P&gt;Follow &lt;A href="http://discuss.develop.com/archives/wa.exe?A2=ind0405b&amp;amp;L=dotnet-rotor&amp;amp;T=0&amp;amp;F=&amp;amp;S=&amp;amp;P=148"&gt;this link&lt;/A&gt; for more details. While you're at it, &lt;A href="http://discuss.develop.com/archives/wa.exe?SUBED1=dotnet-rotor&amp;amp;T=0"&gt;jump on the list&lt;/A&gt; too!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=162105" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>Back from Singapore Rotor Workshop</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/06/20/160861.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/06/20/160861.aspx</id><published>2004-06-21T00:53:00Z</published><updated>2004-06-21T00:53:00Z</updated><content type="html">&lt;p&gt;A month and a half since my last post - I've been&amp;nbsp;slacking off. I do have a good excuse though, visited a couple of countries (more on that), and as a result have been digging myself out of e-mail hell. I'm cooking up the final episode in the series of &lt;A href="http://blogs.msdn.com/joelpob/archive/2004/04/23/119171.aspx"&gt;Late-bound invocation notes&lt;/a&gt;, should have that posted out very soon. &lt;/p&gt; &lt;p&gt;Recently,&amp;nbsp;myself and &lt;a href="http://www.razorsoft.net/weblog/"&gt;Peter&lt;/a&gt; traveled to Singapore for the Asia-Pacific Rotor Workshop, the first RW in the region. It was great fun, had an excellent array of speakers: &lt;a href="http://www.softwareautomata.com/"&gt;John Gough&lt;/a&gt;, &lt;a href="http://www.cosc.canterbury.ac.nz/~nigel/"&gt;Nigel Perry&lt;/a&gt;, &lt;a href="http://www.csse.monash.edu.au/~namtt/"&gt;Nam Tran&lt;/a&gt;, &lt;a href="http://dcooney.com/"&gt;Dominic Cooney&lt;/a&gt;, &lt;a href="http://cs.anu.edu.au/~Andrew.Gray/"&gt;Andrew Gray&lt;/a&gt;, &lt;a href="http://csce.unl.edu/~witty/"&gt;Witty&lt;/a&gt;,&amp;nbsp;and more. All things languages and virtual machines were talked about, full of all sorts of interesting Rotor and CLI/CLR stuff. Kudos' to the &lt;a href="http://www.microsoft.com/singapore/"&gt;Microsoft Singapore&lt;/a&gt; &lt;a href="http://www.thespoke.net/MyBlog/Stanley/MyBlog.aspx"&gt;guys&lt;/a&gt;&amp;nbsp;for a fun four days, and excellent hospitality. I took a quick photo of some of the speaker lineup, while they listened to&amp;nbsp;a talk&amp;nbsp;-&amp;nbsp;I believe it was Andrew Gray speaking at the time, about his &lt;a href="http://jmtk-sscli.sscli.net/"&gt;MMTk Rotor port&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;center&gt;&lt;img src="http://server01.webpipe.com.au/images/singaporespeakers.jpg" /&gt;&lt;/center&gt; &lt;center&gt;&amp;nbsp;&lt;/center&gt;Will be back on air with more soon...&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=160861" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>Type.InvokeMember bug - a small Rotor debugging exercise</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/05/06/127620.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/05/06/127620.aspx</id><published>2004-05-07T02:19:00Z</published><updated>2004-05-07T02:19:00Z</updated><content type="html">&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I figured I&amp;#8217;d go exploring through the Rotor debugger today &amp;#8211; we had a bug come in for Type.InvokeMember() where we throw a System.IndexOutOfRangeException unexpectedly. If you&amp;#8217;re trying to invoke a method on a class which has an overload that takes &amp;#8220;params&amp;#8221; args, chances are you&amp;#8217;ll run in to it. To firm this up, take a look at the C# file &amp;#8211; you&amp;#8217;ll notice a params string[] args, and a string arg1, string arg2. What happens if we try to call the method with two arguments?&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;using&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt; System;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;using&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt; System.Reflection;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt; &lt;SPAN style="COLOR: blue"&gt;class&lt;/SPAN&gt; MainClass&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:place w:st="on"&gt;Main&lt;/st1:place&gt;(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;[] args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(MainClass).InvokeMember("MyMethod", System.Reflection.&lt;SPAN style="COLOR: teal"&gt;BindingFlags&lt;/SPAN&gt;.Public | System.Reflection.&lt;SPAN style="COLOR: teal"&gt;BindingFlags&lt;/SPAN&gt;.Static | System.Reflection.&lt;SPAN style="COLOR: teal"&gt;BindingFlags&lt;/SPAN&gt;.InvokeMethod, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[] { "test", "me" });&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; MyMethod(&lt;SPAN style="COLOR: blue"&gt;params&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;[] args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; s &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: navy"&gt;Console&lt;/SPAN&gt;.WriteLine(s);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; MyMethod(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; arg1, &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; arg2)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: navy"&gt;Console&lt;/SPAN&gt;.WriteLine(arg1);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: navy"&gt;Console&lt;/SPAN&gt;.WriteLine(arg2);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;As it turns out, C# will just call MyMethod(string arg1, string arg2). However, Type.InvokeMember behaves differently. We get an exception:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;C:\repro&amp;gt;clix invokememberbug.exe&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;at System.DefaultBinder.FindMostSpecific(ParameterInfo[] p1, Int32[] paramOrder1, ParameterInfo[] p2, Int32[] paramOrder2, Type[] types, Object[] args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;at System.DefaultBinder.FindMostSpecificMethod(MethodBase m1, Int32[] paramOrder1, MethodBase m2, Int32[] paramOrder2, Type[] types, Object[] args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;at System.DefaultBinder.BindToMethod(BindingFlags bindingAttr, MethodBase[] match, Object[]&amp;amp; args, ParameterModifier[] modifiers, CultureInfo cultureInfo, String[] names, Object&amp;amp; state)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;at System.RuntimeType.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;at MainClass.Main(String[] args) in C:\repro\invokememberbug.cs:line 8&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;IndexOutOfRangeException? That can&amp;#8217;t be right. Either it hit the correct method (it&amp;#8217;s up for debate which method it should hit), or throw an AmbigousMatchException, like usual. Our preference is for AmbigousMatchException.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Well, the object of the blog post is to prove it&amp;#8217;s a bug, and not bad client code: lets cook this up in cordbg. We end up throwing the exception here: &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Times New Roman'"&gt;C:\repro&amp;gt;cordbg clix invokememberbug.exe&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Times New Roman'"&gt;Microsoft (R) Shared Source CLI Test Debugger Shell Version 1.0.0003.0&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Times New Roman'"&gt;Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Times New Roman'"&gt;(cordbg) run clix invokememberbug.exe&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Times New Roman'"&gt;(cordbg) g&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;DefaultBinder.cs&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;671:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;private static int FindMostSpecific(ParameterInfo[] p1, int[] paramOrder1,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;672:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ParameterInfo[] p2, int[] paramOrder2,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;673:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Type[] types, Object[] args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;674:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;679:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;if (args != null &amp;amp;&amp;amp; args[i] == Type.Missing)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;680:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;continue;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;681:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Type c1 = p1[paramOrder1[i]].ParameterType;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;682:*&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Type c2 = p2[paramOrder2[i]].ParameterType;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Lets check the length and the index:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) print p1&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;p1=(0x00b77e70) array with dims=[2]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;p1[0] = (0x00b77b20) &amp;lt;System.Reflection.ParameterInfo&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;p1[1] = (0x00b77b88) &amp;lt;System.Reflection.ParameterInfo&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) print p2&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;p2=(0x00b77e88) array with dims=[1]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;p2[0] = (0x00b77c70) &amp;lt;System.Reflection.ParameterInfo&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) print i&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;i=0x00000001&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) print paramOrder1[1]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;paramOrder1[1]=0x00000001&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) print paramOrder2[1]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;paramOrder2[1]=0x00000001&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) print p2[1]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;Array index out of range.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;Variable unavailable, or not valid&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;As it turns out, indexing into p2[1] is takes you out of range of the array &amp;#8211; there&amp;#8217;s our bug. Okay, so we have a bug in the default binder &amp;#8211; this is great, my client code should work, it&amp;#8217;s the binder that blew up &amp;#8211; we&amp;#8217;ve found our bug. But why? &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Turns out that part is a little more tricky. What does FindMostSpecific do? Intuition tells you that it&amp;#8217;s probably got a couple of methods parameters, from methods that look similar and it needs to find the best fit (verification of this means looking at the defaultbinder.cs source code, but we&amp;#8217;ll keep going&amp;#8230;). What is it passing in? Let us look up the stack:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) up&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;821:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;int res = FindMostSpecific(m1.GetParameters(), paramOrder1, m2.GetParameters(), paramOrder2, types, args); &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) funceval System.Object::ToString m1&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;Function evaluation complete.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;$result=(0x00b8101c) "Void MyMethod(System.String, System.String)"&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) up&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;821:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;int res = FindMostSpecific(m1.GetParameters(), paramOrder1, m2.GetParameters(), paramOrder2, types, args);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;(cordbg) funceval System.Object::ToString m2&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;Function evaluation complete.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;$result=(0x00b81084) "Void MyMethod(System.String[])"&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;We looked up the stack (into FindMostSpecificMethod), found that we were invoking FindMostSpecific with the parameters of two methods, m1 and m2. Surprise surprise. Turns out the code wrapped around FindMostSpecificMethod passes in two methods that could be matches, and asks FindMostSpecificMethod to figure that out. It then calls a helper method FindMostSpecific.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;It looks like FindMostSpecific relies on the fact that the two methods parameters it has to sort and identify as the most specific, are the same length as the InvokeMember object args list. In this case, MyMethod(params string[] args) is clearly only length 1, and the InvokeMember object array is length 2. Quite simply - &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;the binder found a couple of matches, asked the helper methods to go figure it out, but the assumption was that the helper methods would always receive a parameter list the same length as the args list. Clearly a bug. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Of course, you could dig a little deeper to find out where in the binder the logic exists to collect the methods that look like they could be a target invocation match &amp;#8211; but I&amp;#8217;ll leave that exercise up to the reader. I hope you caught the general theme &amp;#8211; think you&amp;#8217;ve found a bug? Okay, go away and take a peek. ;)&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Have fun&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=127620" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>Rotor Whidbey fun - building and running on Longhorn</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/05/05/126837.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/05/05/126837.aspx</id><published>2004-05-06T00:47:00Z</published><updated>2004-05-06T00:47:00Z</updated><content type="html">&lt;P&gt;Just thought I'd post a small screenshot of Rotor Whidbey running on a Longhorn build - we speculated if it'd even build, but as it turns out, coupled with the latest Whidbey C++ compiler it built and ran fine. As a side tidbit, we've got daily tarballs being generated from the latest CLR source checkins - however sometimes we experience a bit of lag, trying to update the CLR source checkins&amp;nbsp;to be cross platform friendly. &lt;/P&gt;
&lt;P&gt;The screenshot is Longhorn with a 5/5/04 build of Rotor Whidbey running &amp;#8220;Hello World&amp;#8220;. &lt;/P&gt;
&lt;P&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.razorsoft.net/images/rotorlonghorn.png"&gt;&lt;/CENTER&gt;
&lt;P&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=126837" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry><entry><title>More late-bound invocation scenario notes</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/joelpob/archive/2004/04/23/119171.aspx" /><id>http://blogs.msdn.com/joelpob/archive/2004/04/23/119171.aspx</id><published>2004-04-23T20:47:00Z</published><updated>2004-04-23T20:47:00Z</updated><content type="html">&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;There are various other scenario&amp;#8217;s in the invocation space that have not been dissected. I mentioned a few of them in the comments section of &lt;A href="http://blogs.msdn.com/joelpob/archive/2004/04/01/105862.aspx"&gt;one of my other posts&lt;/A&gt;. To be a little more illustrative, this posting will iterate over some of these scenario&amp;#8217;s, and provide notes for each. It&amp;#8217;s worthwhile to remember, this is simply a braindump, and until we&amp;#8217;ve firmed up the story for Whidbey, I wouldn&amp;#8217;t recommend you take this as &amp;#8220;written in stone&amp;#8221;. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Some late bound invocation scenario&amp;#8217;s may include:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;#8226;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Known method signature (parameters), unknown method name and method type&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;#8226;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Known signature and known method name, unknown receiver&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;#8226;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Known name&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I&amp;#8217;ll be talking about the first two for these particular notes.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;1. Known method signature (parameters), unknown method name and method type&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;This scenario is presented by an extensibility mechanism where the user specifies a particular custom attribute on a method with the given signature.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At runtime, the methods with the custom attribute are retrieved and thus the callback is available. In this scenario, the arguments are typically provided by the code invoking the callback (the source) so there is usually no coercion/conversion that needs to happen before hand. There is generally nothing unknown at the point of invocation. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Invocation through reflection is very heavy for such scenario&amp;#8217;s, and a delegate is the right solution. Reflection invocation is heavy because there is a single entry point, so it&amp;#8217;s forced to do heavy lifting, like hit metadata to understand the method, signature walking, argument checking etc. If the signature is known, a delegate is definitely the right choice. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The delegate story has an interesting spin to it. When you create a classic delegate over an instance, it is tied one-to-one to the instance of that type.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the delegate is over a static function you don&amp;#8217;t need to worry about the instance, so the type of the method does not come in to the picture &amp;#8211; it&amp;#8217;s a simple question of scoping. If the delegate is over an instance, then you have the issue of the instance possibly changing. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Note:&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;It&amp;#8217;s worthwhile explaining the last sentence a little further. Consider the following: Class A { void M() } and a delegate void &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:place w:st="on"&gt;&lt;st1:State w:st="on"&gt;del&lt;/st1:State&gt;&lt;/st1:place&gt;(). When I do a Delegate.CreateDelegate() over the instance of A.M, and my instance of A changes to another instance of A, I need to recreate the delegate. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;So consider the scenario where the instance is not always stable, we have introduced the recreation of the delegate into the picture. So now it&amp;#8217;s a tradeoff between recreating the delegate and invoking, or using a MethodInfo.Invoke. We can either create the delegate multiple times for each instance, or we can cook up a MethodInfo, and utilize the MethodInfo&amp;#8217;s independent binding to the instance (via the API &amp;#8211; specifying the receiver object). &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;We have to consider the performance aspects here: creation of the delegate is pretty much the same as the binding of the MethodInfo, and Delegate.Invoke is much faster than MethodInfo.Invoke. The ratio we need to consider to produce a working result, is the ration of creation to invocation. If the ratio is one to one, the MethodInfo.Invoke is probably a better solution. If the ratio of invocation over creation is high, than delegate makes sense. If the ratio is different than these options, the user of the API should go away and think about what make sense (ie: benchmark and find out). There is no real concrete story here, as always, we recommend that the user measure their scenario.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;2. Known signature and known method name, unknown receiver&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;This scenario is very similar to the previous model, except that the method is identified by name and not via a custom attribute. Besides the startup logic (actually binding to the method), the considerations for the previous case are very similar. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;An alternative to these cases in a fully trusted application, is the use of the IL instruction &amp;#8220;calli&amp;#8221;. The obvious drawback of calli is the unverifiable nature of the instruction. Because of this, erroneous usage of calli may lead to type safety and security holes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, if used correctly, calli offers a great benefit in both speed and working set performance. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;One obvious advantage of calli over delegates is that it binds to a signature and can take different types of instances. The usage of delegates requires that the delegate must be recreated when the instance changes. Calli uses a function pointer (IntPtr value) that can be retrieved at startup (Give me the MethodInfo, then the MethodHandle and then call GetFunctionPointer), and is extremely light.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Note:&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Obviously, you can&amp;#8217;t generate a calli call in C#. The way out of this if you&amp;#8217;re using C#, you can generate an assembly (Reflection.Emit, ILASM etc) that has a method that takes an IntPtr, and performs a calli. One other thing to note, C++ uses calli extensively for virtuals and invocation. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Trusted components (particularly system components) that have tight performance requirements should pay great consideration to this late bound invocation solution.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=119171" width="1" height="1"&gt;</content><author><name>joelpob</name><uri>http://blogs.msdn.com/members/joelpob.aspx</uri></author></entry></feed>