Lập trình C# - Phần 4: C# Nâng cao

Không gian tên là một định nghĩa m ới trong ngôn ngữ máy tính, nhưng chúng rất hữu dụng, và một số có thể chứng minh rằng sự tồn tại của chúng là cần thiết. Một trong những vấn đề lớn nhất của lập trình là quá tải tên (name overlapping). Hãy nói bạn tạo một rừng các lớp cho chương trình của bạn, và sau đó bạn muốn nhập thư viện của một người nào khác để giúp cho chương trình của bạn. Điều gì sẽ xảy ra nếu một số lớp của người đó có cùng tên với các lớp của bạn, nhưng làm các việc khác nhau? Thật không may, điều đó xảy ra rất nhiều.

pdf17 trang | Chia sẻ: lylyngoc | Lượt xem: 1546 | Lượt tải: 2download
Bạn đang xem nội dung tài liệu Lập trình C# - Phần 4: C# Nâng cao, để 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 4: C# Nâng cao Trang 1 Lập trình C# Dịch từ cuốn sách Beginning C Sharp Game Programming Phần 4: C# Nâng cao Không gian tên (Namespace) Không gian tên là một định nghĩa mới trong ngôn ngữ máy tính, nhưng chúng rất hữu dụng, và một số có thể chứng minh rằng sự tồn tại của chúng là cần thiết. Một trong những vấn đề lớn nhất của lập trình là quá tải tên (name overlapping). Hãy nói bạn tạo một rừng các lớp cho chương trình của bạn, và sau đó bạn muốn nhập thư viện của một người nào khác để giúp cho chương trình của bạn. Điều gì sẽ xảy ra nếu một số lớp của người đó có cùng tên với các lớp của bạn, nhưng làm các việc khác nhau? Thật không may, điều đó xảy ra rất nhiều. Lấy ví dụ, cả Direct3D và DirectSound đều có các lớp tên là Device, và bạn rõ ràng không thể có hai lớp có cùng tên. Không gian tên làm nó trở nên đơn giản, vì vậy bạn có thể ám chỉ các thiết bị khác nhau như Direct3D.Device và DirectSound.Device. Bạn có thể nghĩ không gian tên giống như một thành phố. Nếu bạn chỉ nói với một người nào đó rằng bạn sống ở đường Nguyễn Văn Cừ (chẳng hạn), thì có đến hàng ngàn đường Nguyễn Văn Cừ trong đất nước. Nếu muốn xác định chính xác bạn sống ở đâu, bạn cần phải nói với người đó cả thành phố bạn sống nữa. Tạo ra một không gian tên giống như việc cụ thể thành phố và đường của bạn mà trong đóbạn có thể đặt một số lớp (đường xá) bên trong một không gian tên xác định (thành phố), do đó chương trình của bạn sẽ được phân chia gọn gàng hơn. Bạn có thể cho hầu như mọi thứ vào một không gian tên, bao gồm lớp, cấu trúc, trích xuất và cả một không gian tên khác! Hình 4.1 cho thấy một ví dụ về không gian tên. Hình 4. 1 Đây là hai không gian tên, System và Chapter04. Trong các không gian tên là các không gian tên con và các lớp. Không gian tên System Không gian tên Chapter04 Không gian tên System.Data Không gian tên System.Collections Lớp System.Console Lớp Chapter04.Spacesation Lớp Chapter04.Spaceship Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 4: C# Nâng cao Trang 2 Không gian tên rất tuyệt bởi vì bạn có thể phân cấp chúng – bạn có thể cho nhiều không gian tên vào một không gian tên đang tồn tại. Ví dụ, .NET framework bắt đầu với không gian tên System, với các không gian tên khác trong nó, như là System.Data hay System.Collections. Không gian tên phần cấp cho phép bạn tạo cả những hệ thống phân cấp lớn hơn, giống như Việt Nam tồn tại ở Đông Nam Á, Thành phố Hồ Chí Minh tồn tại trong Việt Nam, và đường Nguyễn Văn Cừ tồn tại ở Thành phố Hồ Chí Minh. Tạo Không gian tên Đây là một số mã mô tả việt sử dụng một không gian tên: namespace Chapter04 { class Spaceship { // Mã ở đây }; class Spacestation { // Mã ở đây }; } Và sau đó, ở bên ngoài không gian tên, bạn sẽ truy cập các lớp đó như thế này: Chapter04.Spaceship s = new Chapter04.Spaceship(); Một tính năng khác của không gian tên là chúng có thể được phân chia thành nhiều phần. Ví dụ, bạn có thể có mã như thế này trong một tập tin: namespace Chapter04 { class Spaceship // blah blah } và sau đó cho một trạm không gian vào một tập tin khác: namespace Chapter04 { class Spacestation // blah blah } Trình dịch C# sẽ tự động ghép các không gian tên cho bạn, vì vậy bạn không phải cho tất cả vào một tập tin lớn. Sử dụng Không gian tên Khi bạn đang ở trong một không gian tên, bạn có thể sử dụng tất cả những gì trong không gian tên đó mà không cần phải định danh nó. Nếu bạn muốn truy cập lớp Spaceship bên trong lớp Spacestation trong ví dụ trước tôi cho bạn thấy, thì bạn chỉ cần đánh vào Spaceship và C# sẽ cho rằng bạn đang nói đến Chapter04.Spaceship bởi vì bạn đang ở trong cùng không gian tên. Tuy nhiên, nếu bạn đang ở ngoài không gian tên, bạn phải định danh không gian tên bằng cách gõ Chapter04. phía trước. Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 4: C# Nâng cao Trang 3 Đương nhiên, gõ Chapter04.Spaceship nhiều lần có thể gây phiền toái một lúc, đặc biệt là bạn biết rằng bạn chỉ sử dụng Spaceship trong Chapter04 chứ không phải nơi nào khác. May mắn thay, bạn được phép nói cho trình dịch C# rằng bạn muốn sử dụng tất cả những gì trong không gian tên đó, bằng cách sử dụng từ khóa using. Sử dụng nó như thế này: // Ở phía trên của mã nguồn: using Chapter04; // phía sau trong tập tin: Spaceship s = new Spaceship(); Ghi chú Từ khóa using có thể được đặt ở một số nơi. Từ khóa không thể được đặt trong một lớp, cấu trúc hay trích xuất, nhưng nó có thể đặt ở gần như mọi chỗ khác. Thực tế thì nó thường được đặt ở đầu tập tin mã nguồn, vì vậy bạn sẽ biết những thư viện nào bạn cần ngay tức thì. Bí danh của Không gian tên Không gian tên phân cấp có thể gây phiền toái. Có thể bạn chưa thấy điều đó, nhưng khi bạn đi sâu vào lập trình DirectX, bạn sẽ hét lên “Microsoft chết tiệt!” ở torng cổ họng của bạn… trừ khi bạn biết về bí danh cho không gian tên. Mọi thứ liên quan đến Direct3D đều ở bên trong không gian tên Microsoft.DirectX.Direct3D. Vậy nếu bạn muốn truy cập một thiết bị Direct3D, bạn sẽ phải gõ Microsoft.DirectX.Direct3D.Device, đúng không? Thật may mắn, đặt bí danh cho không gian tên sẽ làm mọi thứ tốt hơn! Về cơ bạn, bạn có thể lấy một không gian tên và nói với C# cho nó một bí danh. Đây là một bí danh cho không gian tên Direct3D: using D3D = Microsoft.DirectX.Direct3D; D3D.Device d; // thay cho: Microsoft.DirectX.Direct3D.Device d; Hãy xem, đặt bí danh cho không tên gian làm mọi thứ đơn giản như thế nào? Tính đa hình (Polymorphism) Chủ đề về tính đa hình rất là rộng và phức tạp – các trường đại học thường mở cả khóa học về chủ đề này. Tôi có thể cho bạn cái nhìn thoáng qua về chủ đề này. Nhưng dù sao bạn cũng không cần phải học bất cứ quá phức tạp về tính đa hình. Về ngôn ngữ, cái từ đa hình nghĩa là “nhiều dạng”. Trong ngôn ngữ máy tính, tính đa hình cho phép bạn tương tác với nhiều đối tượng khác nhau mà không cần lo về việc những đối tượng này thực sự là gì. Đâu là một ví dụ đời thực của tính đa hình theo nghĩa của ngôn ngữ máy tính, hãy nghĩa về một cái xe hơi. Bạn vào một chiếc xe, mở nó lên, đạp chân ga, và bạn biết điều gì sẽ xảy ra: Chiếc xe bắt đầu chạy! Bây giờ ra khỏi chiếc xe đó, vào một chiếc xa hoàn toàn khác, và làm tương tự: Chiếc xe đó cũng bắt đầu chạy! Cá hai chiếc xa đều có chung giao diện (interface), và bạn thực sự không cần quan tâm làm sao động cơ hoạt động ở bên dưới. Cho dù bạn đang lái một cái xe bốn xi lanh bình thường, một chiếc xe đua tám xi lanh, hay một chiếc xa hơi điện, bạn biết rằng khi đạp ga, chiếc xe bắt đầu Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 4: C# Nâng cao Trang 4 chạy. Đây là ví dụ tốt nhất cho tính đa hình. Máy vi tính gọi một đối tượng làm việc, và đối tượng đó, không quan tâm nó là gì, sẽ làm việc. Đa hình cơ bản Hãy nói bạn có một cây phân cấp rất cơ bản: một gốc và hai con. Gốc là Spaceship (tàu vũ trụ) và các con là CombatShip (tàu chiến) và CargoShip (tàu chở hàng), như hình 4.2. Hình 4. 2 Một cây phân cấp đơn giản Bạn có thể chơi với chúng như bình thường bạn vẫn làm: Spaceship s = new Spaceship(); CargoShip c = new CargoShip(); Đương nhiên, không có gì mới. Nhưng điều đặc biệt là một CargoShip là một Spaceship cho phép bạn thực hiện một vài thủ thuật. Nhìn dòng mã này: Spaceship s = new CargoShip(); Đoạn mã đó hoàn toàn hợp lệ. Dù sao, một CargoShip là một SpaceShip, vì vậy nó sẽ có nghĩa khi làm một Spaceship trỏ tham chiếu tới một CargoShip, đúng không? Có một giới hạn cho điều này: Tham chiếu SpaceShip sẽ không cho phép truy cập những phần riêng nào trong lớp CargoShip mà nó không thừa kế từ SpaceShip. Giả sử rằng SpaceShip có hàm Refuel, và CargoShip có hàm LoadCargo, thì hãy nhìn vào đoạn mã ví dụ sau: Spaceship s = new CargoShip(); s.Refuel(); // ok // s.LoadCargo(); // LỖI BIÊN DỊCH. SpaceShip không được LoadCargo CargoShip c = (CargoShip)s; // vì vậy, chuyển nó thành CargoShip c.LoadCargo(); // ok Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 4: C# Nâng cao Trang 5 Bất kể khi nào mà bạn có một tham chiếu đến một lớp, bạn chỉ có thể truy cập vào những tính năng của lớp xác định, bất kể nếu đối tượng thực sự có thể hỗ trợ nhiều tính năng hơn nữa. Ghi chú Ghi chú rằng bạn không thể sử dụng tính đa hình theo chiều ngược lại. Nếu bạn cố gắng viết CargoShip c = new SpaceShip();, bạn sẽ có một lỗi biên dịch. Một SpaceShip không phải là một CargoShip. Hàm ảo (Virtual Function) Một trong những khía cạnh quan trọng nhất của tính đa hình là ý tưởng về một hàm ảo. Một hàm ảo cơ bản cho phép bạn định nghĩa một hàm trong lớp ốc và sau đó có thể thay đổi nó. Hãy nói như thế này, mọi tàu vũ trụ lo việc bị bắn bởi laser một cách khác nhau, vì vậy bạn định nghĩa việc xử lý việc đó trong lớp SpaceShip gốc. Sau đó, bạn đề nghị rằng tàu chiến có thể lo việc bị trúng đạn một cách khác bởi vì chúng có giáp tốt hơn. Hàm ảo cho phép bạn giải quyết tình huống này một cách dễ dàng, như bạn sẽ thấy trong những mục sau. Khi không có Hàm ảo Đây là một số mã sẽ làm rõ cái gì sẽ xảy ra trong ví dụ của tôi mà không có hàm ảo: class Spaceship { public void LaserHit() { // Thiệt hại nhiều } } class CombatShip : Spaceship { public void LaserHit() { // Thiệt hại ít } } Điều mà tôi vừa làm là tạo một lớp SpaceShip và mặc định làm cho tàu bị nhiều thiệt hại khi bị trúng laser. Tôi muốn CombatShip sẽ bị thiệt hại ít hơn bởi vì chúng có nhiều giáp hơn, vì vậy tôi tạo một hàm LaserHit mới thực hiện thiệt hại ít hơn. Đoạn mã làm chính xác những gì bạn nghĩ là: Spaceship s = new Spaceship(); CombatShip c = new CombatShip(); s.LaserHit(); // Thiệt hại nhiều c.LaserHit(); // Thiệt hại ít Không có thủ thuật gì ở đây. Nhưng về các mã này thì sao? Spaceship s = new Spaceship(); Spaceship c = new CombatShip(); s.LaserHit(); // Thiệt hại nhiều c.LaserHit(); // Thiệt hại nhiều... tại sao? Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 4: C# Nâng cao Trang 6 Điểm khác nhau là gì ? Thay vì sử dụng một tham chiếu CombatShip như ví dụ đầu tiên, tôi lại sử dụng tham chiến SpaceShip thay vào đó, vì vậy tại sao CombatShip lại bị thiệt hại giống như một SpaceShip bình thường? Lý do là hàm LaserHit của SpaceShip không bao giờ biến mất – nó vẩn ở đó. Khi bạn gọi c.LaserHit(), nó gọi SpaceShip.LaserHit() bởi vì nó biết c là SpaceShip. Vì sao trình biên dịch quá ngu ngốc khi không nhận ra c thực sự là một CombatShip đang ngụy trang ? Đó là cách mà trình biên dịch phải làm việc, nếu bạn muốn nó thực hiện theo cách mà bạn muốn nó thực hiện, bạn phải dùng tính ảo. Chào mừng đến với tính Ảo Hàm ảo là một phát minh tuyệt vời. Chúng cũng không thực sự phức tạp. Trước khi tôi giải thích về chúng, để tôi thay đổi các định nghĩa lớp của SpaceShip và CombatShip từ mục trước, để thêm vào vài từ khóa trong các định nghĩa hàm : class SpaceShip { virtual public void LaserHit() { // Thiệt hại nhiều } } class CombatShip : Spaceship { override public void LaserHit() { // Thiệt hại ít hơn } } Hai điểm nhỏ đã được thay đổi: từ khóa virtual đã được thêm và hàm SpaceShip.LaserHit, và override được thêm vài CombatShip.LaserHit. Bây giờ, nếu bạn chạy mã này, nó sẽ làm chính xác những gì bạn muốn: Spaceship s = new Spaceship(); Spaceship c = new CombatShip(); s.LaserHit(); // Thiệt hại nhiều c.LaserHit(); // Bây giờ thiệt hại ít hơn rồi. Hooray! Tại sao cái này lại hoạt động? Khai báo một hàm virtual nói với trình biên dịch rằng hàm này có thể bị thay thế bằng một phiên bản khác trong một lớp con. Nó nói: “Hey, hàm LaserHit này hoạt động với tất cả SpaceShip đó, như một số SpaceShip sau này có thể thay đổi nó!.” Tương tự, khai báo một hàm override nói với trình biên dịch rằng hàm đó là ghi đè lên một phiên bản cũ hơn. Nó nói: “Hey, tôi biết hàm này được khai báo sớm hơn rồi, nhưng phiên bản mới này tốt hơn nè, nên hãy thay thế cái trước đó!” Ghi chú Nếu bạn không sử dụng từ khóa override khi khai báo CombatShip.LaserHit, thì bạn sẽ đi vào chung vấn đề trước đó. Mọi CombatShip, khi được xử lý như SpaceShip, sẽ gọi SpaceShip.LaserHit thay vì cái hàm mà bạn muốn nó gọi. Bạn phải khai báo rõ ràng là một hàm là ghi đè lên phiên bản cũ hơn. Ngôn ngữ như C++ và Java không yêu cầu điều này, vì vậy nó có thể gây một chút lầm lẫn với bạn lần đầu tiê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 4: C# Nâng cao Trang 7 Ghi chú Từ khóa trái ngược với override là từ khóa new. Để trở lại với tình trạng ban đầu, bạn sẽ gõ new public void LaserHit() thay vì override public void LaserHit(). Điều nàu sẽ ngăn SpaceShip thế chỗ phiên bản mới; phiên bản cũ sẽ được gọi khi bạn đang làm việc với một tham chiếu SpaceShip, và phiên bản mới sẽ được gọi khi bạn làm việc với một tham chiếu CombatShip. Trừu tượng (Abstraction) Bạn đôi khi gặp một tình huống mà bạn không biết hành vi mặc định của một lớp gốc là gì. Có thể bạn sẽ nhận ra rằng câu nói “mọi tàu vủ trụ sẽ bị trúng laser theo cách này” là một cách nói ngu ngốc bởi vì mỗi tàu vũ trụ là khác nhau và dù sao đi nữa, bạn cũng ghi đè hàm LaserHit trong mỗi lớp con. Vậy tại sao phải định nghĩa hàm Spaceship.LaserHit trong lần đầu tiên? Trong trường hợp này, bạn sẽ muốn sử dụng một tính năng gọi là trừu tượng. Hàm Spaceship.LaserHit là trừu tượng – bạn không biết các tàu sẽ bị trúng laser như thế nào, nhưng bạn vẫn biết mọi tàu vẫn có thể bị trúng laser. Nếu bạn đơn giản loại bỏ hàm LaserHit khỏi lớp Spaceship, bạn sẽ làm mọi chuyện rói tung lên: Spaceship s = new CargoShip(); s.LaserHit(); // Lỗi! Spaceship không biết bị trúng laser như thế nào Thật may mắn, C# cho bạn một cách để nói, “Mọi tàu vũ trụ biết làm sao khi trúng laser, nhưng tôi chưa chắc chắn nó làm như thế nào.” Đây là một định nghĩa lại của lớp Spaceship: abstract class Spaceship { abstract public void LaserHit(); } Bây giờ bạn có một lớp Spaceship, và bạn biết rằng tất cả tàu vũ trụ có thể bị trúng laser. Điều này sẽ ảnh hưởng như thế nào? Liệu dòng mã sau có hợp lệ? Spaceship s = new Spaceship(); // Lỗi! Oops. Bạn không thể tạo Spaceship thêm được nữa. Điều này OK, bởi vì bạn có lẽ không muốn làm điều đó nữa – thay vào đó bạn có lẽ muốn tạo CombatShip và CargoShip: Spaceship s1 = new CargoShip(); Spaceship s2 = new CombatShip(); s1.LaserHit(); s2.LaserHit(); Ghi chú Bạn không thể làm nhanh các lớp trừu tượng. Hơn nữa, nếu bạn có bất kỳ hàm trửu tượng nào trong lớp, lớp đó cũng phải được khai báo thành trừu tượng. Ghi chú Bất kỳ hàm được khai báo là trừu tượng phải được khai báo như một hàm ghi đè trong lớp con. Nếu bạn không làm điều này, bạn sẽ có một lỗi biên dịch. Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 4: C# Nâng cao Trang 8 Tính đa hình và các Hàm Tôi nghĩ tôi sẽ têm một ghi chú nhỏ trong việc sử dụng tính đa hình với các thông số của hàm, trong trường hợp định nghĩa này vẫn chưa thật sự rõ với bạ. Hãy nói bạn tạo một hàm làm việc với tất cả các loại tàu vũ trụ. Một số thứ như thế này: class Foo { static void ProcessSpaceship( Spaceship s ) { // Một vài mã s.LaserHit(); } } Bạn có thể turyền các tàu chở hàng hay các tàu chiến vào hàm và nó sẽ không quan tâm đến loại tàu vũ trụ của bạn là gì: CargoShip cargo = new CargoShip(); CombatShip combat = new CombatShip(); Foo.ProcessSpaceship( cargo ); Foo.ProcessSpaceship( combat ); Hàm Foo.ProcessSpaceship không quan tâm đến loại tàu nào bạn dùng bởi vì tất cả các tàu có cùng các khả năng cơ bản. Đó là sức mạnh của tính đa hình. Object Trong C#, có một lớp tên là object (đối tượng), nơi mà mọi thứ đều thừa kế tự động. Điều này cho phép bạn lưu trữ dữ liệu trong một đối tượng chứa một các dễ dàng (bạn sẽ thấy trong mục sau của phần này). Hãy nhìn đoạn mã này: object o = new CargoShip(); o = new int(); o = new float(); o = new WeebulCapacitorInfluxGasket(); Object có thể lưu bất cứ cái gì. Sử dụng lớp object là một cách dễ dàng để biến kiểu giá trị - như kiểu số dựng sẵn hay các cấu trúc – thành kiểu tham chiếu. Điều này được thực hiện bởi vì object có thể được sử dụng như là một cách đóng gói kiểu giá trị. Khi bạn cho một kiểu giá trị vào một object, object lập tức cấp phát bộ nhớ cho kiểu giá trị đó, sao chép giá trị và trỏ nó tới bộ nhớ mới. Hãy nhìn mã sau: int x = 10; object o = x; // o bây giờ trỏ tới bản sao của số nguyên 10 x = 20; // thay đổi x; o sẽ không thay đổi bởi vì nó được sao chép x = (int)o; // mở gói o, x bây giờ lại là 10 Đoạn mã đó cho bạn thấy làm sao để thực hiện việc đóng gói và mở gói cơ bả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 4: C# Nâng cao Trang 9 Ghi chú Bất kể khi nào bạn mở gói một object, bạn phải gọi kiểu ban đầu một cách rõ ràng (hay một số kiểu liên quan, nếu nó có thể tương thích). Sự chuyển đổi ngầm là không thể xảy ra. Mảng (Array) Bạn biết đấy, tôi thực sự không thể tin được là phải học lâu như vậy mới đến phẩn mảng này. Tôi có thể nói điều gì – C# là một cái thứ ngôn ngữ phức tạp chết tiệt. Mảng là những hộp chứa cho phép bạn lưu trữ một số đối tượng trong nó. Cơ bản, bạn cần một số cách để lưu trữ rất nhiều dữ liệu, và sử dụng các biến bình thường để lưu tất cả sẽ trở nên tẻ nhạt một cách rất nhanh chóng: Spaceship s1; // ok Spaceship s2; // meh Spaceship s3; // ok cái này gây phiền phức một chút ... Spaceship s20; // ngón tay bắt đầu đau rồi ... Spaceship s42; // TRỜI ƠI DỪNG LẠI ĐI Thật là kinh khủng khi lưu trữ dữ liệu theo cách đó. Đừng làm vậy. Không bao giờ. Hay tôi sẽ gửi một con sóc đến nhà bạn và nhai dây điện máy vi tính của bạn trước khi bạn nhấn nút Save, sau khi bạn đã dành 10 tiếng đồng hồ để đánh mã trong cơn điên vớ vẩn của bạn. Thay vì phải làm tất cả những thứ ngu ngốc như thế, hãy tạo một mảng, một khối dữ liệu mà bạn có thể truy cập bằng số thứ tự. Một ví dụ cơ bản về Mảng Đây là một ví dụ về sử dụng mảng: int[] array = new int[10]; array[0] = 0; // phần tử đầu tiên là 0 array[1] = 10; // phần tử thứ hai là 10 ... array[9] = 90; // phần tử cuối cùng là 90 Bây giờ bạn có mười số nguyên, và bạn có thể truy cập chúng dễ dàng bằng cách sử dụng ngoặc vuông sau tên mảng. Ghi chú Mảng sử dụng các đánh số từ không, tức phần tử đầu tiên trong bất kỳ mảng nào đều có chỉ số là 0 thay vì 1, theo nhiều người vẫn nghĩ. Điều này nghĩa là mảng trong ví dụ trước chỉ có chỉ số hợp lệ từ 0 đến 9, và 10 là không hợp lệ. Mảng là cái gì? Một mảng, như tôi đã nói từ trước, là một khối dữ liệu. Khi bạn gõ mã sau, nó nói rằng bạn đang tạo một biến tên là a, và một tham chiếu đến một mảng số nguyên: int[] a; Tất cả mảng đều là kiểu tham chiếu, có nghĩa là bạn phải sử dụng từ khóa new để tạo một mảng thực sự: Câu lạc bộ Khoa học - THPT Chuyên Lê Hồng Phong TPHCM LHPSC Lập trình C# - Phần 4: C# Nâng cao Trang 10 a= new int[8]; Dòng mã đó tạo một mảng với tám số nguyên, như cho thấy trong hình 4.3. Hình 4. 3 Hình này cho thấy một mảng gồm tám số nguyên Với tất cả ý đồ và mục đích, bạn có thể điều chỉnh a như những kiểm tham chiếu khác. Đây là một số mã cho thấy làm sao bạn có thể sử dụng mảng: int[] a = new int[10]; int[] b = a; // bây giờ b đã trỏ đến cùng mảng b[0] = 10; // thay đổi b thì cũng thay đổi a int i = a[0]; // i bây giờ là 10 b = null; // b không trỏ đến thứ gì nữa a = new int[20]; // mảng cũ đã bị mất, bị gom rác về sau object c = a; // bạn có thể tạo nó là một kiểu “object” Mảng khá dễ để sử dụng, như bạn đã thấy. Kh
Tài liệu liên quan