C# - C Sharp: Namespace
Namespace trong C# dùng để nhóm các lớp một cách hợp lý và ngăn ngừa hiện tượng xung đột tên giữa các lớp có tên giống nhau.
Namespace cũng giúp giảm đi tính phức tạp khi một chương trình lại được yêu cầu trong các ứng dụng khác nhau.
Ví dụ, Venice là tên của một thành phố của nước Mỹ, và cũng là tên của một thành phố của nước Ý. Ta có thể dễ dàng phân biệt hai thành phố cùng tên này khi kết hợp với tên của quốc gia tương ứng với tên thành phố, chẳng hạn như Mỹ.Venice hoặc Ý.Venice.
Tương tự như vậy, khi làm việc với một dự án lớn, có thể xảy ra tình huống các lớp có tên giống nhau, và điều này sẽ dẫn đến hiện tượng xung đột tên. Vấn đề này có thể được giải quyết bằng cách tạo các namespace khác nhau trong dự án đó và đưa mỗi lớp có tên giống nhau vào một namespace riêng.
Cú pháp
Ta sử dụng từ khóa namespace để tạo một namespace, cụ thể như sau:
Ví dụ, các lớp dưới đây mô tả hai dòng sản phẩm của hai hãng khác nhau:
{
...
}
class SamsungWalkMan
{
...
}
class TiviSony
{
...
}
class SonyWalkMan
{
...
}
Việc đặt tên như ví dụ trên là khá dài và có thể gây khó khăn cho vấn đề bảo trì mã lệnh. Đoạn code dưới đây có thể khắc phục được nhược điểm trên:
{
class Television
{
...
}
class WalkMan
{
...
}
}
namespace Sony
{
class Television
{
...
}
class Walkman
{
...
}
}
Sử dụng Namespace
C# cho phép ta tạo một định danh duy nhất cho mỗi namespace, định danh sẽ được dùng để truy cập vào các lớp trong namespace đó.
Ngoài lớp ra thì những cấu trúc dữ liệu sau đây có thể được đặt trong namespace:
· Interface
Interface (Giao diện) là một kiểu tham chiếu, trong interface chứa các khai báo như event, indexer, các phương thức và các property. Interface được thừa kế bởi lớp, cấu trúc, interface khác và tất cả các khai báo trong interface phải được được thực thi trong các lớp cũng như cấu trúc thừa kế nó.
· Structure
Structure (Cấu trúc) là một kiểu giá trị và nó có thể mang những giá trị có kiểu khác nhau, những giá trị này bao gồm trường, phương thức, hằng, property, indexer, operator và các cấu trúc khác.
· Enumeration
Enumeration (Kiểu liệt kê) là kiểu giá trị và nó chứa một danh sách các hằng có tên, các hằng này còn được gọi là danh sách Enumerator.
· Delegate
Delegate là kiểu tham chiếu do người dùng định nghĩa và nó tham chiếu tới một hoặc nhiều phương thức. Nó có thể được dùng để truyền dữ liệu dưới dạng các tham số cho các phương thức.
Đặc điểm và lợi điểm
Namespace sẽ nhóm các lớp, structure và interface có những đặc điểm tương đồng và liên quan đến nhau thành một nhóm và nhóm này đáp ứng được hai đặc điểm của lập trình hướng đối tượng là đóng gói và trừu tượng.
Đặc điểm của namespace:
· Cung cấp cấu trúc phân cấp giúp định danh một cách logic các nhóm lớp.
· Ta có thể thêm nhiều lớp, structure, enumeration, delegate và interface khi khai báo namespace.
· Các lớp trong cùng một namespace phải có tên khác nhau.
Lợi điểm của namespace:
· Cho phép ta sử dụng nhiều lớp có cùng tên bằng cách đặt các lớp này trong các namespace khác nhau.
· Tạo các mô-đun hệ thống.
Namespace System
.NET Frameworks cung cấp một số namespace hệ thống rất hữu ích, trong các namespace này có thể chứa các lớp, interface, structure, delegate và enumeration. Namespace hệ thống phổ biến nhất là System.
System chứa các lớp (trong đó định nghĩa các kiểu dữ liệu giá trị và kiểu dữ liệu tham chiếu), các interface và các namespace khác. System cũng chứa các lớp cho phép ta tương tác được với hệ thống như các thiết bị nhập và xuất dữ liệu. Những namespace phổ dụng nhất trong System bao gồm:
· System.Collections
Namespace này chứa các lớp và interface trong đó định nghĩa các cấu trúc dữ liệu phức tạp như list, queue, bit array, hash table và dictionary.
· System.Data
Namespace chứa các lớp dùng để tạo các kiến trúc ADO.NET, kiến trúc cho phép bạn xây dựng các thành phần được dùng để chèn, sửa và xóa dữ liệu từ các nguồn dữ liệu khác nhau.
· System.Diagnostics
Chứa các lớp dùng để tương tác với các tiến trình hệ thống, nó cũng cung cấp các lớp dùng để gỡ lỗi (debug) các ứng dụng và theo dõi việc thực thi các mã lệnh.
· System.IO
Chứa các lớp cho phép bạn đọc và ghi các luồng và tập tin dữ liệu.
· System.Net
Chứa các lớp cho phép ta tạo các ứng dụng trên nền web.
· System.Web
Namespace này cung cấp các lớp và interface cho phép giao tiếp giữa trình duyệt và server (máy chủ).
Sử dụng namespace System
System được đưa một cách mặc định vào .NET Framework. System xuất hiện ngay tại dòng đầu tiên của chương trình cùng với từ khóa using đặt trước nó. Để tham chiếu tới các lớp trong một namespace được xây dựng sẵn bạn cần xác định namespace chứa các lớp đó và sử dụng cú pháp sau để khai báo:
Lưu ý là vị trí khai báo này phải nằm ở những dòng đầu tiên của chương trình. Ví dụ:
Bạn cũng có thể không cần phải khai báo các namespace mà vẫn sử dụng được các thành phần trong nó. Tuy nhiên điều nãy sẽ dẫn đến nhược điểm là câu lệnh sẽ dài và vì vậy dễ dẫn tới rối code.
Ví dụ, nếu bạn sử dụng khai báo namespace thì mã lệnh sẽ như sau:
Còn dưới đây là trường hợp không khai báo namespace:
Namespace tùy chỉnh
C# cho phép bạn tạo các namespace riêng của bạn gọi là namespace tùy chỉnh, và các namespace này có tác dụng trên tất cả các ứng dụng khác nhau mà bạn sẽ xây dựng. Trong namespace này bạn có quyền tạo tất cả các loại thành phần giống như những loại namespace có sẵn khác.
Lưu ý: Nếu bạn không khai báo bất kỳ namespace nào trong tập tin (file) nguồn thì trình biên dịch sẽ tự động tạo một namespace mặc định không có tên trong file đó, và namespace này được tham chiếu như là một namespace toàn cục (global).
C# cho phép có nhiều namespace cùng tên trong cùng một file hoặc cùng một chương trình, nhưng các thành phần bên trong chúng phải không được trùng tên nhau.
Ví dụ sau đây cho thấy trong cùng một file bạn có thể làm được điều này:
{
class A
{
}
}
namespace A
{
class B
{
}
}
Nhưng bạn không được làm như sau:
{
class A
{
}
}
namespace A
{
interface A /* sai, vì thành phần này cũng có tên là A giống ở trên, mặc dù ở trên là class A còn đây là interface A */
{
}
}
C# cũng cho phép tách các thành phần của cùng một namespace và đặt ở các file khác nhau, việc này sẽ giúp ta có thể dễ dàng hơn trong vấn đề quản lý code. Ví dụ, ta có namespace sau:
{
class B
{
}
class C
{
}
class D
{
}
}
Bây giờ ta sẽ tách namespace A ở trên thành 3 phần và đặt ở 3 file khác nhau:
file thứ nhất (giả sử có tên là B.cs):
{
class B
{
}
}
file thứ hai (giả sử có tên là C.cs):
{
class C
{
}
}
file thứ ba (giả sử có tên là D.cs):
{
class D
{
}
}
Lưu ý khi tạo namespace tùy chỉnh
· Tất cả các thành phần tương tự nhau (class, interface, ...) cần phải được tạo trong một namespace. Điều này sẽ tạo ra một nhóm logic các kiểu tương tự nhau và điều này cũng sẽ giúp tìm kiếm các lớp tương tự nhau một cách dễ dàng.
· Cần tránh việc thiết kế các thành phần nằm quá sâu bên trong các namespace, vì điều này sẽ dẫn đến vấn đề là khó tìm đến được các thành phần sâu bên trong đó.
Ví dụ, ta nên tránh việc làm như sau:
{
namespace B
{
namespace C
{
namespace D
{
class E //việc tìm đến class E trở nên khó khăn
{
}
}
}
}
}
· Cần tránh việc tạo quá nhiều namespace dẫn đến khó kiểm soát code. Nói chung cần xây dựng code sao cho càng đơn giản càng tốt.
Bổ từ truy cập cho namespace tùy chỉnh
Mặc định namespace luôn có bổ từ truy cập là public, và bạn sẽ không thể sử dụng bất kỳ bổ từ truy cập nào cho nó (kể cả bổ từ public). Như vậy thì namespace luôn cho phép các thành phần khác nằm ngoài nó truy cập đến nó. Ví dụ:
/*trình biên dịch sẽ báo lỗi vì đã sử dụng bổ từ truy cập cho namespace*/
{
Tên chính tắc
Một lớp khi đã được khai báo trong các namespace thì thông thường nếu bạn muốn sử dụng tên lớp này bạn sẽ phải thông qua các namespace bao ngoài nó. Cách sử dụng tên lớp như vậy được gọi là tên chính tắc. Tên chính tắc có nhược điểm là kích thước tên dài và tên sẽ được sử dụng trong toàn bộ chương trình. Ví dụ:
Ở ví dụ trên ta thấy, trong phương thức demo() của lớp Y bạn muốn tạo ra thể hiện d của lớp D thì bạn phải bắt đầu từ namespace đầu tiên (nằm ngoài cùng) rồi đi dần vào trong để tới được lớp D, và bạn phải lặp lại điều này để tạo được thể hiện d1 của lớp D. Bạn có thể khắc phục được nhược điểm này nếu bạn sử dụng tên không chính tắc.
Tên không chính tắc
Sau khi bạn khai báo một lớp nằm trong các namespace, thì bạn vẫn có thể sử dụng tên lớp này một cách trực tiếp mà không cần phải thông qua tên của các namespace bao ngoài nó bằng cách khai báo các namespace thông qua sử dụng từ khóa using, và tên lớp như vậy gọi là tên không chính tắc. Tên không chính tắc có ưu điểm là kích thước tên ngắn và vì vậy góp phần làm chương trình trở nên đơn giản và dễ đọc hơn. Ví dụ dưới đây sẽ khắc phục được nhược điểm của ví dụ ở phần Tên chính tắc:
Namespace lồng
C# cho phép bạn tạo namespace nằm trong namespace khác theo hướng phân cấp cha>con>cháu>... gọi là namespace lồng (nested namespace). Namespace lồng trở nên hữu dụng khi một tổ chức hay một công ty nào đó vận hành nhiều dự án một lúc; khi đó tên của namespace đầu tiên có thể là tên của tổ chức hoặc công ty, tên của các namespace bên trong có thể là tên của các dự án hoặc môđun khác nhau. Điều này sẽ giúp cho các nhà phát triển lưu trữ các lớp quan trọng trong các namespace một cách hợp lý để các lớp hay các thành phần khác dễ tương tác.
Cú pháp tạo namespace lồng
Ví dụ:
Ví dụ trên cho thấy lớp ChiTietLuong được tạo nằm bên trong hai namespace lồng nhau là Luong và LienHe.
Bí danh cho namespace
Bí danh là tên thay thế tạm thời của một thực thể. Namespace được gọi tới với từ khóa using sẽ tham chiếu tới tất cả các thành phần trong namespace đó. Tuy vậy, đôi khi bạn chỉ muốn truy cập đến một thành phần nào đó trong namespace, và vì vậy việc sử dụng bí danh có thể là không cần thiết; nhưng bạn có thể sử dụng bí danh để truy cập dến những thành phần cần thiết mà nhiều khi bắt buộc phải đặt bí danh mới truy cập được, và bí danh cũng có một tác dụng nữa là để tránh việc phải sử dụng tên dài nếu namespace có tên dài hoặc thành phần truy cập nằm sâu bên trong các namespace lồng nhau, và điều này sẽ giúp mã lệnh ngắn gọn và dễ đọc hơn.
Cú pháp tạo bí danh như sau:
Xét đoạn mã sau đây:
Đoạn mã trên có hai điểm nhấn:
- Thứ nhất là việc đặt bí danh cho namespace NganHang.TaiKhoan.ChiTietNhanVien là NV, từ đó việc truy cập đến lớp NhanVien của namespace này trở nên đơn giản và code dễ đọc hơn. Cụ thể, thay vì phải sử dụng tên lớp là Bank.Accounts.EmployeeDetails.Employees, thì ta chỉ cần sử dụng là NV.NhanVien.
- Thứ hai là việc đặt bí danh cho lớp System.Console là IO, nếu vậy thì thay vì ta phải viết:
, thì ta chỉ cần viết là:
, và tất cả các thành phần khác của lớp System.Console trong chương trình sẽ đều được truy xuất thông qua bí danh IO (IO.Write(), IO.Read(), IO.ReadLine(), ...).