Lập trình C# - Phần 1: Lịch sử của C#

Ngày xửa ngày xưa, ở một vùng đất thần bí xa xôi, một số người tưng tửng đề nghị phát minh ra toán học. Đương nhiên, ở thời kỳ đó, không có thứ gọi là máy tính hay máy vi tính, vì vậy con người phải tính toán bằng tay, trên giấy. Bên cạnh việc phải sử dụng bộ não (một điều khủng khiếp!), tay bạn có thể bị co cứng sau vài trăm phép tính. Điều đó chẳng có gì thú vị! Để giải quyết vấn đề đó, một số người nảy ra một ý tưởng thiên tài đó là tạo ra một cái máy để làm toán thay bạn, thay thế việc viết và suy nghĩ một cách chán ngắt. Con người tạo ra máy vi tính, và thấy nó rất là tốt. Và bây giờ, chúng ta không cần phải chờ như một số người tội nghiệp để thực hiện vài trăm phép tính trên giấy; thay vào đó, chúng ta có một cái máy có thể thực hiện nó trong một khoảng thời gian rất ngắn, và với các kết quả vô cùng chính xác.

pdf5 trang | Chia sẻ: lylyngoc | Lượt xem: 1443 | Lượt tải: 2download
Bạn đang xem nội dung tài liệu Lập trình C# - Phần 1: Lịch sử của C#, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 1: Lịch sử của C# Trang 1 Lập trình C# Dịch từ cuốn sách Beginning C Sharp Game Programming Phần 1: Lịch sử của C# Lịch sử tóm tắt của máy vi tính Ngày xửa ngày xưa, ở một vùng đất thần bí xa xôi, một số người tưng tửng đề nghị phát minh ra toán học. Đương nhiên, ở thời kỳ đó, không có thứ gọi là máy tính hay máy vi tính, vì vậy con người phải tính toán bằng tay, trên giấy. Bên cạnh việc phải sử dụng bộ não (một điều khủng khiếp!), tay bạn có thể bị co cứng sau vài trăm phép tính. Điều đó chẳng có gì thú vị! Để giải quyết vấn đề đó, một số người nảy ra một ý tưởng thiên tài đó là tạo ra một cái máy để làm toán thay bạn, thay thế việc viết và suy nghĩ một cách chán ngắt. Con người tạo ra máy vi tính, và thấy nó rất là tốt. Và bây giờ, chúng ta không cần phải chờ như một số người tội nghiệp để thực hiện vài trăm phép tính trên giấy; thay vào đó, chúng ta có một cái máy có thể thực hiện nó trong một khoảng thời gian rất ngắn, và với các kết quả vô cùng chính xác. Ngôn ngữ máy (Machine language) và hợp ngữ (Assembly language) Trong những thời kỳ trước đây, máy vi tính rất là đơn giản. Các máy vi tính sớm nhất chỉ hỗ trợ tám lệnh khác nhau, và chỉ có thể thực thi vài chục lệnh. Cơ bản, một lập trình viên tạo ra một danh sách số, đưa nó vào máy vi tính, và chạy nó; các số biểu thị các lệnh. Ví dụ đơn giản, số 0 có thể biểu thị một lệnh cộng, và số 1 biểu thị cho lệnh nhân. Chương trình được viết theo kiểu đó được gọi là viết theo ngôn ngữ máy. Với các máy đơn giản như những máy vi tính đầu tiên, một người khá dễ dàng khi nhớ số nào biểu thị cho lệnh nào – và dù sao đi nữa thì cũng chỉ có tám lệnh. Tuy nhiên, máy vi tính trở nên phức tạp hơn. Người ta bắt đầu thêm nhiều và nhiều lệnh hơn nữa, và chúng ta sớm có vài chục lệnh, thậm chí lên tới một trăm. Rất ít người có thể nhớ hết được nhiều lệnh như vậy, và tra cứu chúng bằng tay là một công việc vô cùng tẻ nhạt. Vậy là hợp ngữ ra đời. Một hơp ngữ là một ngôn ngữ cần thiết để thông dịch trực tiếp các lệnh dựa trên các từ sang ngôn ngữ máy. Ví dụ, một máy vi tính được đề cập ở trên, có mã máy để nhân 6 lần 7 như sau: 1 6 7 với 1 biểu thị lệnh và hai số đằng sau biểu thị dữ liệu của nó. Đương nhiên, việc tra cứu hàng trăm dòng lệnh của thể làm đau mắt bạn (và cả não nữa), vì vậy, hợp ngữ có thể là cái gì đó như thế này: MUL 6, 7 Ah, bây giờ nó dễ chịu hơn với đôi mắt của chúng ta! Ít nhất bây giờ bạn có thể nói ngay tức thời là bạn muốn nhân 6 với 7. Máy vi tính có chương trình gọi là trình dịch hợp ngữ, nó có thể dịch trực tiếp từ hợp ngữ sang ngôn ngữ máy. Trình dịch hợp ngữ là một chương trình rất là đơn giản; về cơ bản, những gì chúng làm là tìm tên lệnh và thay thế chúng bằng những số biểu thị lệnh đó. Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 1: Lịch sử của C# Trang 2 Tính di động Và bây giờ, hãy nói về tính di động. Tính di động đặc trưng cho khả năng di chuyển một chương trình từ máy vi tính này sang một máy khác. Tính di động, cho đến ngày nay, vẫn là một cái mụn nhọt lớn dưới mông. Bạn có thể thấy, có một số người tạo ra máy vi tính ở trong thời xưa, và gần như không máy tính nào làm việc cùng nhau. Vì vậy, bạn có một cái máy có thể hiểu là 1 tức là lệnh nhân, nhưng một cái máy khác có thể áp dụng chúng một cách ngớ ngẩn, và nói rằng 2 mới biểu thị phép nhân. Hợp ngữ giúp giải quyết một vài vấn đề. Bạn có thể cho rằng hầu hết các máy đều có các lệnh cộng trừ nhân chia, và cơ bản là bạn cần một trình dịch hợp ngữ cho máy A để dịch “MUL” ra 1, và một trình dịch khác cho máy B để dịch “MUL” ra 2. Về lý thuyết, bạn có thể mang một chương trình viết bằng hợp ngữ sang nhiều máy khác nhau, giả dụ như các máy tính này đều có một trình dịch hợp ngữ có thể hiều cú pháp hợp ngữ của bạn đang dùng. Nhưng điều này nhanh chóng trở nên tồi tệ. Có thể thấy, máy vi tính trở nên phức tạp hơn nữa, và tất cả các công ty máy vi tính đều muốn thêm càng nhiều lệnh trong một bộ xử lý càng tốt. Nhưng không công ty nào muốn chấp nhận lệnh nào họ nên dùng. Một số máy vi tính có các lệnh để thực hiện phép toán trên số phẩy động, nhưng một số khác thì không. Một số có thể thực hiện phép tính thập phân và một số khác nữa thì không. Và có những máy cho phép hàng tá cách để truy cập vào bộ nhớ, và một số khác thì chỉ có một cách. Houston, chúng ta có vấn đề. Trình dịch hợp ngữ không thể di chuyển chương trình từ một nền tảng sang một nền tảng khác được nữa. Và vì thế, thay vì tạo ra một chương trình cho tất cả mọi máy, nhiều lập trình viên học cách để sử dụng một máy, và tạo chương trình chỉ cho máy đó. Muốn chạy một chương trình tạo ở máy A trên máy B? Trông chờ vận may? Điều đó sẽ chẳng bao giờ xảy ra. Ngôn ngữ cấp cao cứu ngày hôm nay Bước vào ngôn ngữ cấp cao, chính xác. Đây là những ngôn ngữ có độ phức tạp cao có thể được mô tả bằng các biểu thức toán học, nhưng không đi vào tất cả những chi tiết bừa bộn để thực hiện chúng. Bạn có thể biểu diễn một thứ nào đó như thế này: int i = 6 * 7; Trong một ngôn ngữ giống C (một trong những ngôn ngữ cấp cao sớm nhất và phổ biến nhất), một chương trình được gọi là trình biên dịch sẽ dịch những văn bản đó thành mã máy cho bạn. Bạn thực sự không cần phải biết điều gì đang xảy ra – những gì cần biết là bạn tạo ra một con số lưu trữ kết quả 6 nhân 7. Thật không may, những ngôn ngữ cấp cao đã thất bại trong việc tạo ra một chường trình có tính di động hoàn hảo. Vấn đề là mỗi trình biên dịch là khác nhau, và thực hiện cái việc khác nhau. Mỗi hệ điều hành sẽ có một Giao diện Lập trình Ứng dụng (API – Application Programming Interface) khác nhau và không thể sử dụng trên máy khác. Nếu bạn tạo một chương trình Windows, bạn có thể xử lý với WIN32 API, nhưng không thể làm cho nó hoạt động trên một máy Macintosh. Tính di động của Máy ảo Sau đó, một số đã có một ý tưởng thiên tài là phát minh ra Máy ảo (Virtual Machine – VM). Một máy ảo là một bộ xử lý máy vi tính được mô phỏng bên trong phần mềm. Lấy ví dụ, hãy nói rằng bạn đang tạo một ngôn ngữ máy cho riêng bạn. Điều đó thật thuyết, nhưng nếu bạn không có một bộ xử lý cho riêng bạn, điều đó trở nên vô dụng. Vì vậy, bạn bạn tiếp tục tạo nên một mảng của phần mềm và đó Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 1: Lịch sử của C# Trang 3 được gọi là máy ảo. Phần mềm sẽ đọc các mã máy của chính bạn và dịch chúng sang các lệnh của máy tính đang chạy. Hình 1.1 diễn tả quá trình này Hình 1.1 Một máy ảo dịch lệnh để chạy trên một máy thật. Vậy lợi ích của việc này là gì? Tại sao không viết chương trình của bạn trên ngôn ngữ máy thật trong lần đầu tiên? Đáp án là tính di động. Hãy tưởng tượng nếu bạn có thể ra ngoài vào tạo máy ảo cho mười nền tảng khác nhau. Bây giờ bạn có thể tạo một chương trình bằng ngôn ngữ máy ảo của bạn, và chạy nó trên mười máy hoàn toàn khác nhau! Hình 1.2 diễn tả làm sao nó hoạt động. Hình 1.2 Bạn có thể chạy một chương trình trên nhiều nền tảng khác nhau khi sử dụng máy ảo. Một trong các máy ảo phổ biến nhất đánh vào nền công nghiệp máy vi tính là Máy ảo Java (JVM), được phát minh dựa vào ngôn ngữ lập trình Java. Ý tưởng đã tạo ra một ngôn ngữ máy tính có thể chạy trên bất cứ máy tính nào và bất cứ đâu – 100% tính di động. Nó cho phép các nhá phát triển tạo ra một chương trình và bán nó cho bất kỳ máy tính nào có JVM, và không phải dành nhiều giờ và rất nhiều tiền để làm cho nó hoạt động trên một nền tảng khác. Lợi ích có thể thấy dễ dàng là các nhà phát triển có thể mở rộng phạm vi đối tượng. Không chỉ cho các chương trình hoạt động trên Windows, mà còn có thể hoạt động trên Macintosh hoặc Linux. Trong khi điều này nghe có vẻ tuyệt vời về mặt lý thuyết và Java trở thành một ngôn ngữ rất phổ biến, thì nó có nhiều hạn chế. Vấn đề đầu tiên, đương nhiên, là tốc độ. Xuất hiện máy ảo, điều đó có nghĩa Mã trên máy ảo Máy ảo (biên dịch mã) Mã trên máy thật Máy thật (thực thi mã) Chương trình của bạn Máy ảo Windows Windows Máy ảo Linux Linux Máy ảo Macintosh Macintosh Máy ảo Sparc Sparc Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 1: Lịch sử của C# Trang 4 là bất kỳ thứ gì cũng phải qua máy ảo trước khi nó được thực thi bởi máy thật. Và tốc độ là một điều cần thiết với máy vi tính, chúng ta luôn muốn máy tính càng nhanh chừng nào càng tốt. .NET đến giải cứu Và vì thế, .NET ra đời. Microsoft đã chú ý tới sai lầm của Sun khi tạo ra Java và cố gắng sửa nó bằng .NET. Nó không giải quyết được hết, nhưng nói chung, .NET là một sự cải tiến lớn của Java, và hoàn thành nhiều thứ mà Java thất bại. Nền tảng Microsoft .NET là một mạng lưới công cụ thiết yếu và rất phức tạp bao gồm tất cả mọi thứ từ bảo mật Web. Phần thú vị nhất của .NET là Common Language Runtime (CLR), nó là một máy ảo giả để thực thi Ngôn ngữ Biên dịch Microsoft (Microsoft Interpreted Language – MSIL). .NET không bó buộc vào bất kỳ một ngôn ngữ lập trình cụ thể nào. Microsoft chính thức hỗ trợ bốn ngôn ngữ .NET khác nhau:  C++ đã được quản lý  C#  Visual Basic.NET  J# Có hàng tá ngôn ngữ không chính thức nữa có trình biên dịch tạo ra mã MSIL. Những ngôn ngữ này bao gồm LISP, PERL, Python, và COBOL. Và phần tốt nhất của .NET, là điều mà mọi thứ trong .NET đều chia sẽ một cấu trúc chung, được gọi là Hệ thống Kiểu Chung (Common Type System). Về cơ bản, nếu bạn tạo một lớp trong một ngôn ngữ (như Visual Basic), cho nó hai số nguyên, và biên dịch nó, sau đó tạo một lớp tương đương trong C# với dữ liệu giống vậy thì về lý thuyết chúng có cùng chung mã MSIL. Bất kỳ thứ gì biên dịch bằng .NET cũng có thể truy cập bằng .NET, điều này tạo nên hiệu ứng phụ cho phép nhiều ngôn ngữ khác nhau có thể giao tiếp được với nhau. Ví dụ, nếu bạn sử dụng C#, bạn có thể sử dụng các lớp được tạo ra bởi Visual Basic.NET. Hay tốt hơn, bạn có thể thừa kế từ nó và mở rộng khả năng của nó, tức là bạn có thể có những lớp được tạo bởi hơn một ngôn ngữ. Hệ thống .NET linh hoạt đến khó tin chỉ vì lý do này, chưa có bất kỳ một hệ thống nào cho phép bạn tích hợp nhiều ngôn ngữ một cách dễ dàng như thế. Sự biên dịch Ngay tức thời Mọi máy ảo đều được đặt đầu tiên, như đã đề cập tới từ trước. Tuy nhiên, hệ thống .NET không phải là một máy ảo thuần túy. Hệ thống .NET thực hiện một số thứ rất thông minh: nó sử dụng một phương thức gọi là biên dịch Ngay tức thời (Just In Time – JIT) để tăng tốc độ thực thi mã. Hệ thống JIT sẽ theo dõi mã MSIL của bạn, và bất cứ khi nào bạn chạy một module lần đầu tiên, nó lấy đoạn mã MSIL và chuyển nó thành mã máy bản địa.Vì vậy, khi bạn chạy một module .NET trên Windows lần đầu tiên, JIT tải mả MSIL, dịch trực tiếp nó sang mã x86, và lưu mã đó. Từ đó, khi nào module của bạn được chạy, máy vi tính sẽ thực thi mã x86 bản địa và bỏ qua việc sử dụng máy ảo, vì vậy nó có vẻ là được biên dịch trực tiếp từ ngôn ngữ cấp cao sang mã máy – nhưng không hoàn toàn. Hình 1.3 mô tả quá trình này. Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 1: Lịch sử của C# Trang 5 Lý thuyết lược giảm Ý tưởng đằng sau .NET và máy ảo nói chung là các chương trình viết bằng ngôn ngữ cấp cao luôn luôn có thể giảm kích cỡ và lược bớt. Ví dụ, ý tưởng in chữ ra màn hình. Trong ngôn ngữ C#, nó có thể được thực hiện chỉ bằng một dòng mã: System.Console.WriteLine( “I like pies” ); Nhưng dòng đó thực sự đã làm gì? Máy vi tính cơ bản sẽ dịch chuyển một vài vùng nhớ lòng vòng và gửi cho các input/output một số dự liệu đến màn hình. Về lý thuyết, bất kỳ lệnh phức tạp trong bất kỳ ngôn ngữ nào đều có thể được lược giảm xuống một số lệnh đơn giản. Hình 1.3 Module MSIL của bạn được biên dịch thành mã thực trong lần thực thi đầu tiên, vi vậy tránh được tình trạng dịch lại mã mỗi lần đoạn mã đó được thực thi lại. Và đây là một ví dụ trong thế giới thực: Khi bạn nhấn nút đánh lửa của một cái xe, cái xe bắt đầu hoạt động; như là một ngôn ngữ cấp cao. Trong cái xe, một dãy các sự kiện xảy ra như: 1. Ắc quy bắt đầu làm quay pít tông. 2. Ắc quy làm bugi đánh lửa. 3. Bugi là nổ hòa khí trong xi lanh. 4. Hòa khí đang nổ làm quay pít tông nhanh hơn. Mỗi dòng lệnh lớn (như là khởi động xe) có thể được phân tích thành nhiều lệnh nhỏ hơn (như là danh sách liệt kê ở trên). Và chỉ có một số loại lệnh nhỏ khác nhau, mà máy ảo dựa vào đó. Trong thực tế, mọi máy tính đều làm một dãy lệnh thực hiện các phép toán và di chuyển vùng nhớ lòng vòng. Vì vậy, nếu tất cả máy chủ cần phải biết làm sao để thực hiện phép toán và di chuyển vùng nhớ, điều đó có nghĩa là sẽ rất đơn giản khi tạo và di chuyển một chương trình sang nền tảng khác. Tương lai C# là tàu dẫn đường của Microsoft cho nền tảng .NET. Công ty này muốn dùng C++ và sửa những lỗi của nó, và đó là một mục tiêu khá khỏ khăn, nhưng nếu có bất kỳ ai có đủ nguồn lực để thực hiện việc đó, thì đó là Microsoft. Mã MSIL Chạy lần đầu Trình biên dịch JIT Mã bản địa của máy tính Mã bản địa Thực thi lại
Tài liệu liên quan