Cuando las personas hablan sobre el "marco .net", tienden a combinar dos áreas principales: la biblioteca de tiempo de ejecución y la máquina virtual que realmente ejecuta el código .net.
Cuando crea una biblioteca de clases en Visual Studio en C #, la DLL sigue un formato prescrito, más o menos, hay una sección que contiene metadatos que describen qué clases se incluyen y qué funciones tienen, etc. y que describe dónde en el binario existen esos objetos. Este formato .net común es lo que permite compartir bibliotecas entre los idiomas .net (C #, VB.Net, F # y otros) fácilmente. Aunque gran parte de la "biblioteca de tiempo de ejecución" .net está escrita en C # ahora (creo), se puede imaginar cuántos de ellos podrían haberse escrito en idiomas no administrados pero dispuestos en este formato prescrito para que puedan ser consumidos por los idiomas .net .
La verdadera "carne" de la biblioteca que crea consiste en CIL ("Common Intermediate Language"), que es un poco como el lenguaje ensamblador de .net. De nuevo, este lenguaje es la salida común de todos los lenguajes .net, que es lo que hace que las bibliotecas .net sean consumibles por cualquier lenguaje .net.
Con la herramienta "ildasm.exe", que está disponible gratuitamente en los SDK de Microsoft (y puede que ya esté en su computadora), puede ver cómo el código C # se convierte en metadatos e IL. Incluí una muestra al final de esta respuesta como ejemplo.
Cuando ejecuta ejecutar el código .net, lo que sucede comúnmente es que la máquina virtual .net está leyendo esa IL y la está procesando. Este es el otro lado de .net y, nuevamente, es probable que pueda imaginar que esto podría escribirse fácilmente en un lenguaje no administrado: "solo" necesita leer las instrucciones de VM y ejecutarlas (e integrarse con el recolector de basura, que también necesita no ser código .net).
Lo que he descrito es (de nuevo, más o menos) lo que sucede cuando compila un ejecutable en Visual Studio (para obtener más información, recomiendo encarecidamente el libro "CLR a través de C # de Jeffrey Richter", es muy detallado y está excelentemente escrito).
Sin embargo, hay veces que puede escribir C # que no se ejecutará dentro de un entorno .net, por ejemplo, Bridge.NET "compila" el código C # en JavaScript, que luego se ejecuta en el navegador (el equipo que lo produce ha ido a el esfuerzo de escribir versiones de la biblioteca de tiempo de ejecución .net que están escritas en JavaScript y, por lo tanto, el poder y la flexibilidad de la biblioteca .net está disponible para el JavaScript generado). Este es un ejemplo perfecto de la separación entre C # y .net: es posible escribir C # para diferentes "objetivos"; puede orientar el entorno de tiempo de ejecución .net (cuando crea un ejecutable) o puede orientar el entorno del navegador (cuando usa Bridge.NET).
Una clase de ejemplo (muy) simple:
using System;
namespace Example
{
public class Class1
{
public void SayHello()
{
Console.WriteLine("Hello");
}
}
}
Los metadatos e IL resultantes (recuperados a través de ildasm.exe):
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly Example
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 0A 54 65 73 74 49 4C 44 41 53 4D 00 00 ) // ...TestILDASM..
.custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 0A 54 65 73 74 49 4C 44 41 53 4D 00 00 ) // ...TestILDASM..
.custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20 // ...Copyright ..
20 32 30 31 36 00 00 ) // 2016..
.custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 31 39 33 32 61 32 30 65 2D 61 37 36 64 // ..$1932a20e-a76d
2D 34 36 33 35 2D 62 36 38 66 2D 36 63 35 66 36 // -4635-b68f-6c5f6
32 36 36 31 36 37 62 00 00 ) // 266167b..
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 ) // ...1.0.0.0..
.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1C 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework
2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 2E 32 01 // ,Version=v4.5.2.
00 54 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 // .T..FrameworkDis
70 6C 61 79 4E 61 6D 65 14 2E 4E 45 54 20 46 72 // playName..NET Fr
61 6D 65 77 6F 72 6B 20 34 2E 35 2E 32 ) // amework 4.5.2
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module Example.dll
// MVID: {80A91E4C-0994-4773-9B73-2C4977BB1F17}
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x05DB0000
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit Example.Class1
extends [mscorlib]System.Object
{
.method public hidebysig instance void
SayHello() cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "Hello"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Class1::SayHello
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method Class1::.ctor
} // end of class Example.Class1
// =============================================================