Lập trình · Ngôn ngữ lập trình
Hướng dẫn học lập trình C# cơ bản cho người mới
Trả lời nhanh
C# là ngôn ngữ hướng đối tượng kiểu tĩnh của Microsoft, chạy trên .NET, một runtime miễn phí, đa nền tảng cho Windows, macOS và Linux. Hãy cài .NET SDK, chạy dotnet new console, rồi dotnet run sẽ in ra "Hello, World!". Các ý tưởng cốt lõi là lớp và record, collection generic như List<T> và Dictionary<K, V>, truy vấn LINQ, async/await, pattern matching và ngoại lệ.
C# là gì và dùng để làm gì
C# (đọc là "C sharp") được thiết kế tại Microsoft bởi một nhóm do Anders Hejlsberg dẫn dắt và phát hành lần đầu năm 2002. Nó được Ecma chuẩn hóa (ECMA-334) và phát triển công khai cùng .NET. C# được dùng cho web API và trang web (ASP.NET Core), ứng dụng desktop Windows, ứng dụng di động và desktop đa nền tảng (.NET MAUI), dịch vụ đám mây và game: engine Unity dùng C# cho script game. Cú pháp của nó thuộc họ C nên quen thuộc với lập trình viên Java, C++ và JavaScript.
Cài .NET và chạy Hello, world
Tải .NET SDK từ dot.net và kiểm tra bằng dotnet --version. Tạo và chạy một dự án console:
dotnet new console -o HelloApp
cd HelloApp
dotnet run
# Hello, World!Mẫu dự án tạo ra Program.cs, dùng top-level statements, nên với chương trình nhỏ không cần lớp hay phương thức Main:
Console.WriteLine("Hello, World!");Biến và các kiểu dữ liệu cơ bản
Mỗi biến có một kiểu tĩnh. var cho phép trình biên dịch suy luận kiểu từ giá trị. Kiểu giá trị (số, bool, struct) giữ dữ liệu trực tiếp; kiểu tham chiếu (string, lớp, mảng) tham chiếu tới một đối tượng.
| Kiểu | Ví dụ | Ghi chú |
|---|---|---|
int | int n = 42; | Số nguyên 32 bit |
long | long big = 10_000_000_000; | Số nguyên 64 bit |
double | double x = 3.14; | Số thực dấu phẩy động 64 bit |
decimal | decimal price = 19.99m; | Hệ thập phân, phù hợp cho tiền tệ |
bool | bool ok = true; | true hoặc false |
char | char c = 'A'; | Đơn vị mã UTF-16 |
string | string s = "hi"; | Văn bản bất biến |
var name = "Ada";
int count = 7;
double avg = count / 2.0;
Console.WriteLine($"{name} has {count} items, avg {avg}"); // Ada has 7 items, avg 3.5
Console.WriteLine(count / 2); // 3 (integer division)
Console.WriteLine(int.Parse("12") + 1); // 13
string? nickname = null; // ? marks a nullable reference
Console.WriteLine(nickname ?? "none"); // none$"..." là chuỗi nội suy. Các dự án mới bật kiểu tham chiếu nullable, nên trình biên dịch cảnh báo khi giá trị có thể là null được dùng mà không kiểm tra.
Điều khiển luồng và phương thức
int score = 72;
if (score >= 90) Console.WriteLine("A");
else if (score >= 70) Console.WriteLine("B"); // B
else Console.WriteLine("C");
for (int i = 0; i < 3; i++) Console.Write($"{Square(i)} "); // 0 1 4
Console.WriteLine();
foreach (var fruit in new[] { "apple", "pear" }) Console.WriteLine(fruit);
string day = "SAT";
string kind = day switch
{
"SAT" or "SUN" => "weekend",
_ => "weekday",
};
Console.WriteLine(kind); // weekend
Console.WriteLine(Greet("Lin")); // Hello, Lin!
static int Square(int x) => x * x;
static string Greet(string name, string greeting = "Hello") => $"{greeting}, {name}!";Biểu thức switch và mẫu or là một phần của pattern matching trong C#. Phương thức có thể có tham số mặc định, đối số có tên (Greet(name: "Lin")) và thân biểu thức với =>.
Lớp, thuộc tính và record
Lớp có trường, thuộc tính (trường kèm logic get và set) và phương thức. record là kiểu có phép so sánh bằng dựa trên giá trị, lý tưởng cho dữ liệu bất biến.
var acc = new Account("Ann");
acc.Deposit(50);
Console.WriteLine($"{acc.Owner}: {acc.Balance}"); // Ann: 50
var p1 = new Point(3, 4);
var p2 = p1 with { Y = 5 }; // copy with one change
Console.WriteLine(p1); // Point { X = 3, Y = 4 }
Console.WriteLine(p1 == new Point(3, 4)); // True
public class Account
{
public string Owner { get; }
public decimal Balance { get; private set; }
public Account(string owner) => Owner = owner;
public void Deposit(decimal amount)
{
if (amount <= 0) throw new ArgumentException("amount must be positive");
Balance += amount;
}
}
public record Point(int X, int Y);Khai báo kiểu phải đặt sau các top-level statements trong cùng tệp. Lớp hỗ trợ đơn kế thừa (class Savings : Account) và số lượng interface tùy ý.
Collection và LINQ
Các collection generic trong System.Collections.Generic là cấu trúc dữ liệu dùng hằng ngày. LINQ (Language Integrated Query) thêm các phương thức như Where, Select, OrderBy và GroupBy cho mọi collection.
var nums = new List<int> { 3, 1, 2, 5 };
nums.Add(4);
nums.Sort();
Console.WriteLine(string.Join(", ", nums)); // 1, 2, 3, 4, 5
var ages = new Dictionary<string, int> { ["ann"] = 31, ["bob"] = 25 };
ages["cy"] = 40;
if (ages.TryGetValue("bob", out int bobAge)) Console.WriteLine(bobAge); // 25
var evenSquares = nums.Where(n => n % 2 == 0).Select(n => n * n).ToList();
Console.WriteLine(string.Join(" ", evenSquares)); // 4 16
var oldest = ages.OrderByDescending(kv => kv.Value).First();
Console.WriteLine(oldest.Key); // cyCác collection phổ biến khác là HashSet<T> cho phần tử duy nhất, Queue<T>, Stack<T> và mảng kích thước cố định như int[].
Tính năng đặc trưng: async và await
C# đã đưa ra mô hình async/await mà nhiều ngôn ngữ sau này áp dụng. Phương thức async trả về Task và có thể await các thao tác chậm, như yêu cầu web hoặc đọc tệp, mà không chặn luồng.
using System.Net.Http;
using var http = new HttpClient();
var sizes = await Task.WhenAll(
GetLengthAsync(http, "https://example.com"),
GetLengthAsync(http, "https://example.org"));
Console.WriteLine($"downloaded {sizes.Sum()} characters");
static async Task<int> GetLengthAsync(HttpClient http, string url)
{
string html = await http.GetStringAsync(url);
return html.Length;
}Task.WhenAll chạy cả hai yêu cầu cùng lúc và chờ cả hai. Khai báo using var giải phóng HttpClient ở cuối phạm vi.
Ngoại lệ
Lỗi là các ngoại lệ. Hãy bắt các kiểu cụ thể trước, và dùng finally hoặc using để dọn dẹp. Mẫu TryParse tránh ngoại lệ với dữ liệu nhập thường không hợp lệ.
try
{
int age = int.Parse("abc");
}
catch (FormatException ex)
{
Console.WriteLine($"not a number: {ex.Message}");
}
finally
{
Console.WriteLine("done");
}
if (!int.TryParse("41", out int parsed)) parsed = 0;
Console.WriteLine(parsed); // 41Một chương trình nhỏ hoàn chỉnh: tần suất từ
Thay Program.cs trong dự án console bằng đoạn mã này, rồi chạy dotnet run -- notes.txt.
using System.Text.RegularExpressions;
if (args.Length != 1)
{
Console.Error.WriteLine("usage: dotnet run -- FILE");
return 1;
}
try
{
string text = File.ReadAllText(args[0]).ToLowerInvariant();
var top = Regex.Matches(text, "[a-z']+")
.GroupBy(m => m.Value)
.Select(g => (Word: g.Key, Count: g.Count()))
.OrderByDescending(t => t.Count)
.Take(5);
foreach (var (word, count) in top)
Console.WriteLine($"{count,5} {word}");
return 0;
}
catch (FileNotFoundException)
{
Console.Error.WriteLine($"file not found: {args[0]}");
return 1;
}Top-level statements có thể đọc args của dòng lệnh và trả về mã thoát. System.IO, System.Linq và System.Collections.Generic được nhập tự động qua implicit usings trong các dự án mới.
Những lỗi thường gặp của người mới
- Dùng
doublecho tiền; hãy dùngdecimalđể tránh lỗi làm tròn nhị phân. - Bỏ qua cảnh báo nullable, rồi chúng thành
NullReferenceExceptionkhi chạy. - Sửa một
List<T>bên trongforeachtrên chính list đó, sẽ némInvalidOperationException. - Tạo
HttpClientmới cho mỗi yêu cầu trong ứng dụng chạy lâu. Hãy tái sử dụng một thể hiện hoặc dùngIHttpClientFactory. - Quên rằng truy vấn LINQ chạy lười: truy vấn chạy lại mỗi lần được duyệt trừ khi bạn gọi
ToList().
Học tiếp ở đâu
Microsoft Learn có tài liệu C# chính thức, gồm phần tham quan ngôn ngữ và các bài hướng dẫn tương tác. Sau đó học ASP.NET Core cho web API, Entity Framework Core cho cơ sở dữ liệu, hoặc Unity cho game, và dùng xUnit hoặc NUnit để kiểm thử. Visual Studio, VS Code với C# Dev Kit và JetBrains Rider là các trình soạn thảo phổ biến.
Câu hỏi thường gặp
C# chỉ dành cho Windows phải không?
Không. .NET hiện đại chạy trên Windows, macOS và Linux, và ứng dụng C# có thể triển khai lên máy chủ Linux và container. Chỉ một số framework giao diện desktop, như WPF và Windows Forms, là chỉ dành cho Windows.
C# và .NET khác nhau thế nào?
C# là ngôn ngữ lập trình. .NET là runtime và thư viện biên dịch và chạy mã C# (cũng như F# và Visual Basic).
C# có giống Java không?
Có, ở nhiều mặt: cả hai đều là ngôn ngữ hướng đối tượng, kiểu tĩnh, có bộ thu gom rác, với cú pháp kiểu C. C# thêm các tính năng như thuộc tính, LINQ, async/await, struct kiểu giá trị và record.
C# có tốt để làm game không?
Có. Unity, một trong những engine game được dùng nhiều nhất, dùng C# cho script game, và engine Godot cũng hỗ trợ C#.