Khi mọi người nói về "khung .net", họ có xu hướng kết hợp hai khu vực chính - thư viện thời gian chạy và máy ảo thực sự chạy mã .net.
Khi bạn tạo một thư viện lớp trong Visual Studio trong C #, DLL tuân theo một định dạng được quy định - rất đại khái, có một phần chứa dữ liệu meta mô tả các lớp được bao gồm trong đó và những chức năng nào chúng có, v.v. trong nhị phân những đối tượng tồn tại. Định dạng .net phổ biến này là những gì cho phép các thư viện được chia sẻ giữa các ngôn ngữ .net (C #, VB.Net, F # và các ngôn ngữ khác) một cách dễ dàng. Mặc dù phần lớn "thư viện thời gian chạy" .net được viết bằng C # bây giờ (tôi tin), bạn có thể tưởng tượng có bao nhiêu trong số chúng có thể được viết bằng các ngôn ngữ không được quản lý nhưng được sắp xếp theo định dạng này để chúng có thể được sử dụng bởi các ngôn ngữ .net .
"Thịt" thực sự của thư viện mà bạn xây dựng bao gồm CIL ("Ngôn ngữ trung gian chung") hơi giống với ngôn ngữ lắp ráp của .net - một lần nữa, ngôn ngữ này là đầu ra chung của tất cả các ngôn ngữ .net, là ngôn ngữ làm cho các thư viện .net có thể sử dụng được bằng bất kỳ ngôn ngữ .net nào.
Sử dụng công cụ "ildasm.exe", có sẵn miễn phí trong Microsoft SDK (và có thể đã có trên máy tính của bạn), bạn có thể xem cách mã C # được chuyển đổi thành dữ liệu meta và IL. Tôi đã bao gồm một mẫu ở dưới cùng của câu trả lời này làm ví dụ.
Khi bạn chạy mã .net, điều thường xảy ra là máy ảo .net đang đọc IL đó và xử lý nó. Đây là mặt khác của .net và, một lần nữa, bạn có thể tưởng tượng rằng điều này có thể dễ dàng được viết bằng ngôn ngữ không được quản lý - nó "chỉ" cần đọc hướng dẫn VM và chạy chúng (và tích hợp với trình thu gom rác, cũng cần không được mã .net).
Những gì tôi đã mô tả là (một lần nữa, đại khái) những gì xảy ra khi bạn xây dựng một tệp thực thi trong Visual Studio (để biết thêm thông tin, tôi đánh giá cao cuốn sách "CLR qua C # của Jeffrey Richter" - nó được viết rất chi tiết và xuất sắc).
Tuy nhiên, đôi khi bạn có thể viết C # sẽ không được thực thi trong môi trường .net - ví dụ: Bridge.NET "biên dịch" mã C # thành JavaScript, sau đó chạy trong trình duyệt (nhóm sản xuất nó đã đi đến nỗ lực viết các phiên bản của thư viện thời gian chạy .net được viết bằng JavaScript và do đó sức mạnh và tính linh hoạt của thư viện .net có sẵn cho JavaScript được tạo). Đây là một ví dụ hoàn hảo về sự tách biệt giữa C # và .net - có thể viết C # cho các "mục tiêu" khác nhau; bạn có thể nhắm mục tiêu môi trường thời gian chạy .net (khi bạn xây dựng một tệp thực thi) hoặc bạn có thể nhắm mục tiêu môi trường trình duyệt (khi bạn sử dụng Bridge.NET).
Một lớp ví dụ đơn giản (rất):
using System;
namespace Example
{
public class Class1
{
public void SayHello()
{
Console.WriteLine("Hello");
}
}
}
Dữ liệu meta và IL kết quả (được truy xuất thông qua 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
// =============================================================