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.
17 trang |
Chia sẻ: lylyngoc | Lượt xem: 1565 | Lượt tải: 2
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