Advanced
C# Language Features
Các tính năng nâng cao của C#
Indexer
Chỉ số
Không có
indexer
Giả sử ta có 1 đối tượng danh sách lớp, trong đối tượng có chứa danh sách các sinh viên trong 1 lớp
Nếu muốn truy cập đến từng sinh viên trong danh sách, ta phải viết 1 hàm trả về 1 sinh viên và 1
hàm thay đổi giá trị của sinh viên đó
class DanhSachLop
{
List<SinhVien> danhsach;
public SinhVien GetSinhVien(int index)
{
return danhsach[index];
}
public void SetSinhVien(int index, SinhVien sv)
{
danhsach[index] = sv;
}
}
Indexer
C# cung cấp tính năng indexer giúp đơn giản hóa việc truy cập đến 1
sinh viên trong danh sách lớp nói trên. Việc truy cập này tương tự
với việc truy cập đến các kí tự trong 1 xâu
class DanhSachLop
{
List<SinhVien> danhsach;
public SinhVien this[int index]
{
get { return danhsach[index]; }
set { danhsach[index] = value; }
}
}
Indexer
static void Main()
{
DanhSachLop a = new DanhSachLop();
int i = 0;
// Lệnh xử lí
Console.WriteLine(a[i].Name);
//
}
Indexer
Ngoài kiểu tham số là int, ta có thể khai báo tham số có kiểu tùy ý,
số lượng tùy ý
class DanhSachLop
{
List<SinhVien> danhsach;
public SinhVien this[string name]
{
get { }
set { }
}
}
Operator Overloading
Quá tải toán tử
Quá tải toán
tử
C# cho phép ta quá tải các toán tử:
Các toán tử 1 ngôi: !, ++, …
Các toán tử 2 ngôi: +, -, *, /, %, ^, &, |, >>, <<
Các toán tử logic: >, <, >=, <=, ==, !=
Các toán tử +=, -=, *=,… không được phép quá tải, nó sẽ lấy giá trị
quá tải của các phép toán tương ứng
Cú pháp:
public static <kiểu trả về> operator <phép toán>(danh sách số hạng)
VD: public static PhanSo operator +(PhanSo a, PhanSo b)
Ví dụ
class PhanSo
{
int tu, mau;
public static PhanSo operator*(PhanSo a, PhanSo b)
{
return new PhanSo(a.tu * b.tu, a.mau * b.mau);
}
public void InPhanSo()
{
Console.WriteLine("{0}/{1}", tu, mau);
}
public PhanSo(int tu, int mau)
{
this.tu = tu;
this.mau = mau;
}
}
Ví dụ
static void Main(string[] args)
{
PhanSo a = new PhanSo(1, 2);
PhanSo b = new PhanSo(3, 4);
PhanSo c = a * b;
c.InPhanSo();
}
Kết quả
3/8
Chú ý
Khi quá tải các toán tử so sánh, ta phải quá tải các toán tử ngược với
nó: < và >, >= và <=, == và !=
Khi quá tải toán tử ==, ta nên ghi đè các phương thức Equals và
GetHashCode kế thừa từ lớp object
public static bool operator ==(PhanSo a, PhanSo b)
{
return (a.tu == b.tu) && (a.mau == b.mau);
}
public static bool operator !=(PhanSo a, PhanSo b)
{
return (a.tu != b.tu) || (a.mau != b.mau);
}
Type conversions
Chuyển đổi kiểu dữ liệu
Chuyển đổi
kiểu dữ liệu
C# cung cấp cho ta tính năng định nghĩa việc chuyển đổi kiểu dữ
liệu này sang kiểu dữ liệu khác
Có 2 loại chuyển đổi kiểu
Ngầm định: implicit
Tường minh: explicit
Ngầm định: giống như việc chuyển đổi số từ int sang double, ta chỉ
cần gán trực tiếp
Tường minh: giống như việc chuyển đổi số từ double sang int, ta
phải sử dụng toán tử chuyển đổi kiểu (int)
Cú pháp:
public static <loại chuyển đổi> operator <tên kiểu đích>(biến cần
chuyển kiểu);
Ví dụ
class PhanSo
{
int tu, mau;
public static implicit operator double(PhanSo a)
{
return (double)a.tu / a.mau;
}
public static explicit operator int(PhanSo a)
{
return a.tu / a.mau;
}
public PhanSo(int tu, int mau)
{
this.tu = tu;
this.mau = mau;
}
}
Ví dụ
static void Main(string[] args)
{
PhanSo a = new PhanSo(1, 2);
PhanSo b = new PhanSo(15, 4);
double d1 = a; // d = 0.5
int i = (int)b; // i = 3
}
Anonymous Types
Kiểu dữ liệu ẩn danh
Anonymous
Types
C# cho phép ta đóng gói các dữ liệu chỉ đọc (readonly) vào 1 đối
tượng mà không cần khai báo kiểu dữ liệu trước
static void Main(string[] args)
{
var a = new { ID = 1, Name = "Linh" };
Console.WriteLine("{0} {1}", a.ID, a.Name);
}
Thường sử dụng trong các truy vấn LINQ
Chú ý
Ta không thể điều khiển được tên của kiểu ẩn danh
Kiểu ẩn danh luôn kế thừa từ lớp System.Object
Các trường và thuộc tính trong kiểu ẩn danh luôn là chỉ đọc
Kiểu ẩn danh không có các event, phương thức, toán tử, phương
thức ghi đè
Ta không thể kế thừa từ 1 kiểu ẩn danh
Kiểu ẩn danh luôn được khởi tạo bằng hàm khởi tạo mặc định
(không tham số)