CHAPTER 18 UNDERSTANDING CIL AND THE ROLE OF DYNAMIC ASSEMBLIES
•
Building dynamic assemblies using the System.Reflection.Emit namespace. This
API allows you to generate an in-memory .NET assembly, which can optionally be
persisted to disk.
•
Leveraging aspects of the CTS that are not supported by higher-level managed
languages, but do exist at the level of CIL. To be sure, CIL is the only .NET
language that allows you to access each and every aspect of the CTS. For example,
using raw CIL, you are able to define global-level members and fields (which are
not permissible in C#).
Again, to be perfectly clear, if you choose not to concern yourself with the details of CIL code, you
are still absolutely able to gain mastery of C# and the .NET base class libraries. In many ways, knowledge
of CIL is analogous to a C(++) programmer’s understanding of assembly language. Those who know the
ins and outs of the low-level “goo” are able to create rather advanced solutions for the task at hand and
gain a deeper understanding of the underlying programming (and runtime) environment. So, if you are
up for the challenge, let’s begin to examine the details of CIL.
Note Understand that this chapter is not intended to be a comprehensive treatment of the syntax and
semantics of CIL. If you require a full examination of the topic, I’d recommend downloading the official ECMA
specification (ecma-335.pdf) from the ECMA International web site (www.ecma-international.org).
Examining CIL Directives, Attributes, and Opcodes
When you begin to investigate low-level languages such as CIL, you are guaranteed to find new (and
often intimidating-sounding) names for very familiar concepts. For example, at this point in the text, if
you were shown the following set of items
{new, public, this, base, get, set, explicit, unsafe, enum, operator, partial}
you would most certainly understand them to be keywords of the C# language (which is correct).
However, if you look more closely at the members of this set, you might be able to see that while each
item is indeed a C# keyword, it has radically different semantics. For example, the enum keyword defines
a System.Enum-derived type, while the this and base keywords allow you to reference the current object
or the object’s parent class, respectively. The unsafe keyword is used to establish a block of code that
cannot be directly monitored by the CLR, while the operator keyword allows you to build a hidden
(specially named) method that will be called when you apply a specific C# operator (such as the plus
sign).
In stark contrast to a higher-level language such as C#, CIL does not just simply define a general set
of keywords, per se. Rather, the token set understood by the CIL compiler is subdivided into the
following three broad categories based on semantics:
652
•
CIL directives
•
CIL attributes
•
CIL operation codes (opcodes)