CIL is an object-oriented assembly language, and is entirely stack-based. Its bytecode is translated into native code or — most commonly — executed by a virtual machine.
Why do we need CIL? Is it not possible to translate C# into native code instead of CIL? If all .Net languages compile to CIL, why isn't C# used instead of IL? Is CIL more expressive than C# or VB?
The question is more general: why do we need intermediate languages at all? Why many modern high-level languages compile to an intermediate form which is then interpreted/JITed into native code?
First, note that not only .NET uses its own intermediate language. Java has one as well as many, many other languages/platforms.
There are several reasons that favor this approach. The most important is that the intermediate language abstracts the architecture of an runtime environment. It is not tied to any specific architecture, instead, uses some abstractions (for example, in CIL there are no registers although physical machine has registers, in CIL there are local variables which are often JITed to physical registers).
The abstraction means that it is much easier to reason about security and performance. For example, they have a formal theorem that CIL is type-safe, proven by J. Kennedy and D. Syme. Also, abstract intermediate form could potentially be more compact than a platform native code. Another benefit is that actual execution could use the information about a current system, for example the very same CIL executed in 32 vs 64-bit environment could be JITed to different native code, reflecting the availability of 64-bit registers.
http://en.wikipedia.org/wiki/P-code_machine
C# is not a good choice for an intermediate language. Although both CIL and C# are Turing-complete which means that any other programming language could be compiled into both C# and CIL, C# is just too abstract, too high-level. Thus, compiling some non-object languages into C# (functional languages, declarative languages) could potentially require a lot of C# code and the actual execution would be slower comparing to a scenario where all high-level languages target the very same, abstract but still quite low-level intermediate language that can be effectively JITed to a native code.
This is why CIL contains features that are not present in C# and the other way around. For example, CIL supports method pointers and tail calls while C# doesn't need both - but this way some functional languages can be translated in a more effective way. On the other hand, C# has the notion of properties which is not present in CIL - this is because properties can be seen as just a syntactic sugar, not introducing any expressiveness but rather some kind of convenience into the language.