There has been a lot of hype surrounding Microsoft's .NET platform and the new C# language. As a consequence a number of authors and publishers have scrambled to cash in on this hype, and many books on these topics ought never to have been published. These are two of the better books.
Let me start with the .NET CLR book. The first two parts of this, amounting to some 180 pages, contain a good introduction to the Intermediate Language, or IL. An excellent introduction to the opcodes of the IL, the structure of the assembly and the available tools is given. The code examples are in both C# and VB.NET, and occasionally also in Jscript, J#, Perl or VC++. That they are short and not very informative examples of high-level languages I am willing to accept, as their main purpose is to illustrate the various aspects of IL. I consider that to be the best part of the book.
So far so good. Unfortunately, the remaining sections become increasingly flawed. The writing becomes very repetitive at times and could certainly have benefited from some editorial guidance. Similarly, I have a problem with the actual code examples. When an author decides not to show the entire code for a problem, he or she should think very carefully about what parts of the code do get shown. Boilerplate code and trivial expressions can certainly be left out, but far too often they are left in and the more important parts of the code are excluded. This problem is reduced, as the full source code is available for downloading. But I find it annoying when several pages are dedicated to developing an application and all that is used to illustrate it is numerous screen shots instead of showing the actual code. And when you lay down coding guidelines, you should at least follow them yourself.
On the other hand, one of the very good aspects of the book is the coverage of command line tools.
The second book (CIL Programming) complements the first quite nicely. The first part is an introduction to the structure of the assembly and to the IL opcodes. This part is not very well written, but the inside of the back cover contains a table of the basic opcodes. The fourth chapter contains a detailed walk-through of a complete project. The back of the book promises "Loaded with source code and real-world examples - no toy code", which is a bit grand given that we are now at page 121, and we haven't seen an executable program yet. The actual project itself is rather simple - it is a random number generator with a GUI test harness.
It is from here on the book becomes interesting. There is a chapter on debugging, covering both of the tools shipped with the SDK. We have a chapter on how various constructs in various .NET languages (VB.NET, C#, Oberon and Component Pascal) are translated into IL, and how the optimiser handles these. I haven't seen such a chapter before, and I found it very interesting. And finally, there are chapter on emitting types (i.e. writing code which emits IL), dynamic proxies and appendixes on where .NET is heading and what languages are available (including those already mentioned, Perl, Python, Forth, and the functional languages Mondrian and F#). The examples are still relatively simple, but, as mentioned above, this is hardly a big problem.
The second half is, in my view, by far the best part of the book.
To conclude, both books show clear signs of having been written too quickly with little or no editorial guidance. This is a real pity, because if you could somehow merge the two books, with the proper editing, this could have been an excellent book. Still, if you happen to come across a cheap, second-hand copy you may want to take a closer look at it.
Recommended with reservations.