Giới thiệu
C# là ngôn ngữ có vai trò quan trọng nhất trong kiến trúc Microsoft .NET Framework. Trong bài này chúng ta sẽ tìm hiểu:
- Từ phần mềm (software) đến phần cứng (hardware)
- Làm quen môi trường Visual Studio
- Tạo một ứng dụng Console C#
- Hiểu được mục đích của các namespace
- Tạo một ứng dụng đồ hoạ (WPF) đơn giản
Từ phần mềm (software) đến phần cứng (hardware)
Bộ xử lý máy tính chỉ hiểu được các bit (0 hay 1). Việc viết bằng ngôn ngữ máy (dùng bit 0 hay 1) là rất khó khăn cho con người nên các nhà lập trình đã dùng các ngôn ngữ cấp cao để viết chương trình. Ngôn đầu tiên được phát triển là ngôn ngữ Assembly dễ đọc hơn với con người, ví dụ đoạn mã sao chép giá trị 61h vào thanh ghi AL như sau:
MOV AL, 61h
Một chương trình gọi là Assembler sẽ chuyển đoạn mã trên thành ngôn ngữ máy (tức các bit 0 hay 1) để bộ xử lý máy tính có thể thực hiện lệnh.
Mặc dù dễ đọc hơn ngôn ngữ máy nhưng ngôn ngữ Assembly vẫn còn khó để viết hay sửa lỗi chương trình.
Các ngôn ngữ cấp cao như Fortran, Pascal, C++ được phát triển với các câu lệnh phức tạp làm việc ở mức trừu tượng cao hơn so với ngôn ngữ Assembly. Một trình biên dịch (compiler) được dùng để chuyển chương trình mức cao sang ngôn ngữ máy để thực thi như hình minh hoạ sau:
Một vài ngôn ngữ như Java, C#, hay Visual Basic, thêm một bước khác vào trong quá trình chuyển sang ngôn ngữ máy để tăng tính khả chuyển (portable) cho chương trình. Thay vì biên dịch trực tiếp đến ngôn ngữ máy, mã chương trình được chuyển thành ngôn ngữ trung gian, thỉnh thoảng được gọi là bytecode. Sau đó, tại thời điểm chạy chương trình (run time), mã trung gian sẽ được biên dịch thành mã máy để thực thi. Bước chuyển từ mã trung gian đến mã máy còn được gọi là biên dịch Just – in – time (JIT).
Đến thời điểm này chúng ta cần phân biệt 3 khái niệm quan trọng:
- Run time: thời điểm chương trình đang chạy.
- Design time: thời điểm thiết kế hay xây dựng chương trình (viết mã, thiết kế giao diện, v.v.).
- Biên dịch Just –in-time: bước chuyển từ mã trung gian đến mã máy.
Trong các ngôn ngữ .NET như C# hay VB, ngôn ngữ trung gian được gọi là Common Intermediate Language (CIL) và thành phần chuyển ngôn ngữ trung gian sang ngôn ngữ máy được gọi là Common Language Runtime (CLR).
Trong Java, ngôn ngữ trung gian gọi là Java bytecode và thành phần chuyển ngôn ngữ trung gian sang ngôn ngữ máy gọi là Java Virtual Machine (JVM).
Hình ảnh minh hoạ chuyển mã từ ngôn ngữ cấp cao (Java, C# hay VB) sang ngôn ngữ trung gian và cuối cùng là ngôn ngữ máy (xem hình bên dưới):
Môi trường lập trình
Để chương trình có thể được viết, kiểm tra, hay sửa lỗi dễ dàng, cần một môi trường lập trình chứa nhiều công cụ hữu ích còn được gọi là Môi trường phát triển tích hợp (Integrated Development Environment – IDE) như:
- Code Editor: dùng để soạn thảo mã chương trình.
- Debugger: dùng để phát hiện, chỉnh sửa lỗi chương trình.
- Compiler: biên dịch chương trình thành ngôn ngữ trung gian hay máy.
- Build automation tools: cho phép biên dịch tuỳ chọn.
- Testing tools: kiểm tra chương trình.
- Source code management tools: quản lý mã chương trình.
- Object – oriented tools: tổ chức các lớp để dễ hiểu, dễ quản lý hơn.
Visual Studio
Visual Studio là IDE của Microsoft hỗ trợ các ngôn ngữ như C#, Visual Basic, C/C++, F#, v.v. Một vài đặc trưng cơ bản được cung cấp bởi Visual Studio IDE:
- Customizable menus and toolbars :các thực đơn và thanh công cụ tuỳ chọn.
- Customizable windows: các cửa sổ tuỳ chọn.
- Auto hiding windows: các cửa sổ ẩn tự động.
- IntelliSense: hỗ trợ cho viết mã chương trình, dùng phân biệt hoa thường ví dụ first khác First.
- Call stack: hiển thị một loạt các hàm gọi để dẫn đến điểm thực thi hiện tại.
- Sequence diagrams and dependency graphs: cung cấp trong các phiên bản Pro của Visual Studio dùng để cung cấp thông tin về cách các hàm gọi các hàm khác.
Làm quen môi trường Visual Studio
Visual Studio là môi trường lập trình giàu công cụ hỗ trợ xây dựng các dự án nhỏ hay lớn với các ngôn ngữ lập trình trong .NET như C#, Visual Basic (VB), F#, C++. Tôi đang dùng Visual Studio 2012 (Ultimate), khi khởi động thì giao diện sẽ trông như sau:
Để làm quen với C#, chúng ta sẽ bắt đầu với một ứng dụng Console – ứng dụng chạy trên một cửa sổ dòng lệnh (như của sổ Command) và sau đó chúng ta sẽ làm quen với ứng dụng giao diện đồ hoạ WPF.
Chương trình đầu tiên
Tạo một ứng dụng C# Console
Vào File > New > Project. Trong hộp thoại New Project tại mục Installed chọn Templates và chọn Visual C#. Tại khung giữa chúng ta chọn Console Application, đặt tên ứng dụng là MyFirstConsole trong ô Name, chọn vị trí lưu ứng dụng tại ô Location:
Nhấp OK. Giao diện lúc này
Trước khi viết các dòng mã C# đầu tiên, chúng ta lướt qua cửa sổ Solution Explorer để hiểu hơn về cấu trúc của một ứng dụng C# Console, giao diện cửa sổ Solution Explorer (đã mở rộng tất cả các mục):
Solution ‘MyFirstConsole’: là tập tin solution mức cao nhất. Mỗi ứng dụng chỉ có một tập tin solution duy nhất có phần mở rộng là .sln (trong trường hợp này là MyFirstConsole.sln). Trong hình trên chúng ta không thấy tập tin này nhưng chúng ta có thể gõ cụm từ MyFirstConsole trên ô Search Solution Explorer:
Mỗi tập tin solution sẽ chứa các tham chiếu đến một hay nhiều tập tin dự án (project). Ở hình trên chúng ta thấy MyFirstConsole chứa 1 dự án (1 project).
- MyFirstConsole: tên của tập tin dự án có phần mở rộng là csproj (MyFirstConsole.csproj). Mỗi tập tin dự án chứa các tham chiếu đến một hay nhiều tập tin chứa mã C# và các thành phần khác liên quan đến dự án.
- Properties: đây là một thư mục trong dự án. Thư mục này chứa tập tin AssembyInfo.cs – chứa các thông tin liên quan đến dự án như tên tác giả, thời gian viết, v.v.
- References: thư mục này chứa các tham chiếu đến các đoạn mã đã biên dịch (compiled code) mà ứng dụng có thể sử dụng. Khi các đoạn mã này được biên dịch, nó sẽ được chuyển vào trong một assembly với một tên duy nhất. Các nhà phát triển dùng các assembly để đóng gói các đoạn mã hữu ích để chia sẻ cho các nhà phát triển khác sử dụng trong ứng dụng của họ.
- App.config: là tập tin cấu hình, ứng dụng sẽ sử dụng tại thời điểm chạy để thay đổi ứng xử của nó phù hợp với thông tin cấu hình.
- Program.cs: là tập tin chứa mã C# được hiển thị trong cửa sổ soạn thảo. Các đoạn mã trong tập tin này bao gồm mã do Visual Studio sinh ra và mã do người lập trình viết.
Viết chương trình đầu tiên với tính năng Microsoft IntelliSense
Tập tin Program.cs định nghĩa một lớp gọi là Program và lớp này chứa một phương thức tĩnh đặc biệt là Main – nơi bắt đầu của chương trình. Mọi phương thức phải được định nghĩa trong một lớp nào đó.
Chú ý: C# là ngôn ngữ case-sensitive, tức là Main sẽ khác main, vì vậy cần viết chính xác tên (biến, lớp, phương thức, v.v.) trong C#.
Chúng ta sẽ viết lệnh xuất dòng chữ “Hello World” trong hàm Main bằng cách gọi phương thức WriteLine trong lớp Console:
Console.WriteLine("Hello World!");
Chúng ta để ý rằng trước phương thức WriteLine là tên lớp (Console) chứa nó và dấu chấm. Lớp Console được chứa trong namespace System.
Chúng ta có thể tận dụng tính năng Microsoft IntelliSense để rút ngắn thời gian viết mã chương trình. Đây là một tính năng rất hữu ích trong quá trình viết mã có thể thấy rõ khi viết lệnh xuất dòng Hello World.
Trong hàm Main tại dấu ngoặc { chúng ta gõ Enter để bắt đầu hàng mới và viết câu lệnh đầu tiên. Khi chúng ta gõ chữ C thì xuất hiện một danh sách (còn gọi là danh sách IntelliSense):
Trong danh sách có tên lớp Console kèm theo dòng mô tả chức năng của nó. Chọn Console và gõ dấu chấm, một danh sách khác lại xuất hiện:
Trong danh sách này chứa toàn bộ các thành phần của lớp Console. Chọn WriteLine và khi mở ngoặc sẽ xuất hiện các phiên bản khác nhau của WriteLine:
Gõ cụm từ Hello World ! và lưu ý phải đặt trong dấu ngoặc kép, đóng ngoặc đơn và chấm phẩy – các lệnh trong C# khi kết thúc phải có dấu chấm phẩy:
Biên dịch và chạy chương trình
Biên dịch đoạn mã C# bằng cách vào thực đơn Build chọn Build MyFirstConsole. Một cửa sổ Output sẽ xuất hiện bên dưới cửa sổ Code and Text Editor với dòng thông tin:
Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped
Nếu cửa sổ Output không xuất hiện có thể vào thực đơn View chọn Output.
Nếu chương trình chúng ta bị lỗi, bên cạnh cửa sổ Output, chúng ta có thể xem danh sách các lỗi trong cửa sổ Error List (vào thực đơn View > Error List).
Sau khi biên dịch thành công, chúng ta sẽ chạy chương trình bằng cách vào thực đơn Debug chọn Start Without Debugging hay nhấn tổ hợp phím Ctrl + F5
Kết quả:
Cửa sổ dòng lệnh xuất hiện với thông điệp Hello World ! và sẽ đóng khi chúng ta nhấn một phím bất kỳ.
Trong cửa sổ Solution Explorer chọn tập tin dự án MyFirstConsole (không phải tập tin solution) và chọn Show All File trên thanh công cụ của cửa sổ Solution Explorer:
Sẽ xuất hiện hai mục bin và obj:
Hai mục này sẽ tham chiếu trực tiếp đến hai thư mục tên bin và obj được Visual Studio tạo ra khi chúng ta biên dịch (Build) chương trình và chúng chứa phiên bản thực thi (executable version) của chương trình và các tập tin khác dùng để biên dịch và debug ứng dụng.
Mở rộng mục bin sẽ xuất hiện mục Debug. Mở rộng mục Debug (tham chiếu đến thư mục Debug) sẽ thấy nhiều tập tin xuất hiện trong đó có tập tin MyFirstConsole.exe là chương trình chạy khi chúng ta vào Debug > Start Without Debugging:
Namespace (không gian tên)
Namespace là một bộ chứa (container) dùng để chứa một số lượng lớn các chức năng ( thường là lớp) trong .NET Framework hay trong chương trình và chống lại tình trạng xung đột trong trường hợp chia sẻ các thành phần (ví dụ như lớp) có cùng tên (hai lớp có thể có cùng tên, ví dụ MyClass, nhưng phải ở trong hai namespace khác nhau). Ví dụ một namespace tên System chứa lớp Console có phương thức WriteLine mà chúng ta dùng để xuất dòng Hello World!
Có thể truy cập các thành phần trong namspace bằng cú pháp:
tên_namespace.thành_phần_cần_truy_cập
Ví dụ để dùng lớp Console chúng ta viết:
System.Console
Một cách giúp tiết kiệm thời gian cho người lập trình là khai báo namespace chúng ta cần một lần bằng lệnh using tại vị trí đầu tiên trong tập tin Program.cs.
using System;
với khai báo trên, khi sử dụng lớp Console (hay bất kỳ thành phần nào khác trong namespace) chúng ta chỉ cần nêu tên lớp hay thành phần đó, ví dụ Console.
Để hiểu hơn về namespace chúng ta sẽ thực thi trên cửa sổ Code and Text Editor:
– Trong tập tin Program.cs, gõ dấu // trước lệnh using System:
// using System;
Khi thực hiện việc này, chúng ta sẽ thấy lớp Console xuất hiện một đường gợn sóng màu đỏ:
– Vào thực đơn Build chọn Build MyFirstConsole thì xuất hiện lỗi trong cửa sổ Error List như sau:
– Nhấp đôi chuột vào dòng thông báo trong cửa sổ Error List sẽ nhảy đến lệnh gây ra lỗi:
– Chỉnh sửa lại lệnh bằng cách thêm namspace System vào trước Console:
System.Console.WriteLine("Hello World !");
Assemblies
Các lớp được biên dịch trong các assemblies. Một assembly là một tập tin có phần mở rộng là dll hay exe. Một assembly có thể chứa nhiều lớp bao gồm thư viện các lớp .NET Framework (ví dụ lớp System.Console), điều này có thể làm cho assembly trở nên rất lớn và khó quản lý.
Để khắc phục gánh nặng cho một assembly, các lớp .NET Framework được chia vào trong nhiều assemblies theo những chức năng khác nhau như xử lý cơ sở dữ liệu, truy cập web services, xây dựng giao diện đồ hoạ người dùng, v.v.
Nếu muốn sử dụng các lớp trong một assembly nào đó, chúng ta phải thêm vào dự án một tham chiếu (reference) đến assembly đó. Sau đó, dùng lệnh using để có thể sử dụng các thành phần trong namspace trong assembly này.
Một assembly có thể chứa các lớp cho nhiều namespace; một namespace có thể được mở rộng đến nhiều assemblies.
Trong cửa sổ Solution Explorer của dự án MyFirstConsole mở rộng thư mục References chúng ta sẽ thấy các tham chiếu đến các assemblies như Microsoft.CSharp, System, System.Core,…
Tạo một ứng dụng đồ hoạ
Chúng ta đã làm quen với ứng dụng Console – thao tác trên cửa sổ dòng lệnh. Trong Visual Studio chúng ta cũng có thể tạo ra các ứng dụng giao diện đồ hoạ Windows bằng cách cung cấp hai template: Windows Forms Application xuất hiện từ .NET Framework 1.0 và WPF (Windows Presentation Foundation) Application xuất hiện từ .NET Framework 3.0 cung cấp nhiều tính năng đồ hoạ vượt trội so với Windows Form Application và được các chuyên gia khuyên dùng thay cho Windows Forms Application. Trong giáo trình này sẽ dùng WPF Application.
Khi làm việc với ứng dụng đồ hoạ, chúng ta có hai chế độ là Code view và Design View. Code view dùng để viết mã cho chương trình, Design view dùng để thiết kế giao diện cho ứng dụng. Chúng ta có thể chuyển đổi qua lại hai chế độ này.
Chúng ta sẽ làm quen với ứng dụng đồ hoạ Windows thông qua tạo một ứng dụng WPF Application chỉ gồm một form đơn giản chứa một textbox để nhập tên người dùng và một button mà khi nhấp vào sẽ hiển thị thông điệp xin chào cùng với tên người vừa nhập.
Tạo ứng dụng WPF Application đầu tiên
Vào thực đơn File chọn New > Project. Trong hộp thoại New Project chọn Visual C#, WPF Application, đặt tên dự án là MyFirstWPF trong ô Name, và chọn vị trí lưu ứng dụng trong ô Location:
Nhấn OK và giao diện gồm một WPF form (MainWindow) trong cửa sổ Design view và một cửa sổ khác chứa mô tả XAML cho form:
XAML là viết tắt của Extensible Application Markup Language và là một ngôn ngữ tựa XML được dùng bởi ứng dụng WPF để định nghĩa bố cục (layout) và nội dung của một form. Chúng ta có thể tự viết một mô tả XAML trong một trình soạn thảo được gọi là XAMLPad được cài với Windows Software Development Kit (SDK).
Trong thanh Toolbox chọn và mở rộng Common WPF Controls sẽ xuất hiện các thành phần (components) và các điều khiển (controls) có thể được đặt trên một form trong ứng dụng WPF:
Nếu muốn xem nhiều điều khiển hơn có thể mở rộng phần All WPF Controls.
Chọn một Label kéo và thả vào form. Trên form, chúng ta có thể di chuyển Label đến bất cứ vị trí nào chúng ta muốn, trong trường hợp này di chuyển đến góc trái trên của form như hình:
Chọn Label và xem rong cửa sổ XAML xuất hiện dòng mô tả cho Label:
Chọn Label và trong thực đơn View chọn Properties Window. Trong cửa sổ Properties Window tại mục Text chọn kích cỡ chữ là 20px:
Đóng cửa sổ Properties Window, lúc này kích cỡ chữ sẽ lớn hơn lúc trước:
Thông tin XAML của Label lúc này:
<Label Content="Label" HorizontalAlignment="Left" Margin="25,24,-176,0" VerticalAlignment="Top" Height="47" Width="152" FontSize="20" Grid.Column="1"/>
Thuộc tính FontSize của Label là 20. Chúng ta có thể thay đổi giá trị của FontSize đến 12 bằng cách gõ trực tiếp trong mô tả XAML.
Trong mô tả XAML, tại thuộc tính Content của Label đổi giá trị từ Label thành Please enter your name, sự thay đổi sẽ được phản ánh trên form:
Khi bạn chọn Label sẽ xuất hiện khung định dạng kích cỡ và chúng ta có thể thay đổi kích cỡ Label tuỳ ý:
Trở lại thanh Toolbox (nếu đóng thanh Toolbox thì có thể mở lại bằng cách vào View > Toolbox), trong Common WPF Controls chọn Textbox kéo và thả vào form dưới Label. Mở Properties Window của Textbox và thay đổi giá trị của Name thành userName:
Trở lại thanh Toolbox trong Common WPF Controls chọn Button kéo và thả vào form bên phải Textbox. Trong cửa sổ Properties Window của Button thay đổi giá trị của Name là ok, đổi giá trị của Content thành OK:
Nhấp chuột vào thanh tiêu đề của form MainWindow, trong cửa sổ Properties Window của form đổi giá trị của Title thành Hello
Form lúc này trông như sau:
Biên dịch chương trình bằng cách vào Build > Build MyFirstWPF và được xác nhận thành công.
Vào Debug > Start Without Debugging sẽ hiển thị form và chúng ta có thể nhập tên vào Textbox nhưng lúc này button OK vẫn chưa có tác dụng gì:
Đóng Form bằng cách nhấp nút Close (dấu X). Trong cửa sổ Solution Explorer chọn và mở rộng mục MainWindow.xaml sau đó nhấp chuột vào MainWindow.xaml.cs sẽ đến cửa sổ Code and Text Editor với code do Visual Studio sinh ra như sau:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace MyFirstWPF { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } }
Để đến cửa sổ Code and Text Editor chúng ta cũng có thể chọn bất kỳ vị trí nào trong khung Design, kích chuột phải chọn View Code:
Ở đây chúng ta thấy một số namspace được gọi bằng các lệnh using. Lớp MainWindow được thừa kế từ lớp Window với một phương thức đặc biệt gọi là constructor (phương thức khởi tạo) gọi một phương thức khác là InitializeComponent():
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } }
Thực tế code được phát sinh bởi Visual Studio rất nhiều, được mô tả trong XAML nhưng đã được ẩn giấu trước chúng ta.
Trong ứng dụng Console chúng ta đã biết phương thức Main như là điểm bắt đầu của ứng dụng, với ứng dụng WPF chúng ta vào cửa sổ Solution Explorer và nhấp đôi chuột vào mục App.xaml sẽ xuất hiện mã XAML:
Application x:Class="MyFirstWPF.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> <Application.Resources> </Application.Resources> </Application>
Chúng ta thấy thuộc tính StartupUri tham chiếu đến tập tin MainWindow.xaml. Trong ứng dụng WPF, Main không xuất hiện mà sẽ được ẩn và mã phát sinh cho Main dựa vào các thiết lập trong tập tin App.xaml.
Trở lại Form trong chế độ Design (tab MainWindow.xaml), nhấp đôi chuột vào nút OK để trở lại cửa sổ Code and Text Editor (tab MainWindow.xaml.cs) và lần này xuất hiện thêm phương thức ok_Click:
private void ok_Click(object sender, RoutedEventArgs e) { }
Thêm dòng code hiển thị thông điệp cùng với tên người dùng nhập từ Textbox vào trong phương thức ok_Click:
private void ok_Click(object sender, RoutedEventArgs e) { MessageBox.Show("Hello " + userName.Text); }
Trở lại tab MainWindow.xaml (khung Design) và xem trong phần mô tả XAML sẽ thấy dòng code XAML mô tả cho button cùng với phương thức ok_Click được gán đến phần tử Click:
<Button x:Name="ok" Content="OK" Grid.Column="5" HorizontalAlignment="Left" Margin="113,76,0,0" VerticalAlignment="Top" Width="75" Height="35" Click="ok_Click"/>
Vào Debug > Start Without Debugging sẽ xuất hiện Form. Nhập thông tin vào Textbox và nhấp vào button OK: