Jul 8, 2010

Điều gì mới ở C# 4.0

Vấn đề là mằn trong vấn đề... Lọ mọ trên mạng vớ dc bài viết giới thiệu về C# 4.0 nên copy về đây. Không rõ nguồn gốc xuất sứ bài này do ai viết nhưng mà tìm dc bên ddth.com

Thấy cũng hay, bổ ích nhiều vấn đề mới ...

Khi quyển sách này đang được viết, thì phiên bản mới nhất của Microsoft là Visual Studio 2010 Beta 2 và .NET Framework 4.0 Beta 2 đang được giới CNTT tải về để nghiên cứu. Bắt đầu từ ngày 11/02/2010 sắp tới, Microsoft tổ chức những hội nghị mở rộng tại nhiều thành phố lớn trên toàn thế giới để giới thiệu phiên bản mới nhất của Visual Studio và .NET Framework, sẽ được tung ra thị trường vào ngày 22/03/2010.

Thứ nhất, vì phiên bản Visual Studio-2010 chưa được tung ra thị trường, cho nên những chức năng mới của Visual Studio-2010 được viết trong sách này, đều chưa được chính thức công nhận, và có thể có những thay đổi. Tuy nhiên, có thể nói rằng, sẽ không có bất cứ một thay đổi quan trọng nào có thể xảy ra.

Thứ hai, mặc dầu phiên bản mới sắp được phát hành, tất cả những tư liệu dẫn chứng cho những mã nguồn, cũng như những mã nguồn mẫu trong quyển sách này, vẫn là những gì nồng cốt nhất cho một lập trình C#, ngày hôm nay, cũng như sau khi Visual Studio-2010 được phát hành, và chắc chắn rằng vẫn còn là những nồng cốt của một chương trình C# cho tới phiên bản kế tiếp sau phiên bản Visual Studio-2010.

Những chủ đề (themes) của phiên bản C# mới.

Với phiên bản Visual Studio-2010, để có thể thống nhất về con số của những phiên bản, C# 2010 được gọi là C# 4.0, cùng một hệ số với phiên bản .NET Framework 4.0. Do đó, các bạn nên bắt đầu làm quen với cách gọi này: C# 4.0, thay vì C#-2010.

Chủ đề chính được Microsoft hoạch định cho phiên bản C# 4.0 là “Năng Động (Dynamic)”. Tất cả những chức năng mới của phiên bản C# 4.0 đều được phát triển chung quanh hai chữ “năng động”. Và như các bạn đã được biết, lớp đối tượng nền của tất cả các lớp đối tượng trong một lập trình C# là System.Object. Do đó, System.Object bắt buộc phải trở thành một lớp đối tượng có tính năng động. Nói một cách khác, mục tiêu của Microsoft cho phiên bản .NET Framework 4.0 nói chung, và C# nói riêng, là C# phải trở thành một ngôn ngữ có những lớp đối tượng năng động

Nhưng thế nào là lớp đối tượng năng động? Một lớp đối tượng năng động là một lớp đối tượng mà cấu trúc(structure) và trạng thái (behavior) của nó không bị bó buộc hoặc lệ thuộc vào những trạng thái tĩnh (static). Nói một cách khác, một đối tượng lớp không cần phải định nghĩa trước khi khởi tạo, mà có thể được định nghĩa khi bắt đầu khởi tạo trong lúc phần mềm đang vận hành. Và nói một cách khác nữa, một lớp đối tượng năng động là một lớp đối tượng mà biên trình (csc.exe) không biết một tí gì về đối tượng đó khi biên lập.

Những đối tượng (objects) dưới đây là những điển hình của một đối tượng năng động

Đối tượng của những ngôn ngữ lập trình năng động, như Pyphon hoặc Ruby.
Những đối tượng COM được truy cập qua giao ước IDispatch.
Những dạng đối tượng nguyên thuỷ của .NET có thể truy cập qua phép đối xứng (reflection).
Những đối tượng có cấu trúc thay đổi trong khi vận hành, như HTML DOM.

Mặc dầu thế, C# vẫn là một ngôn ngữ nặng tích chất không thay đổi (static), nhưng có khả năng tạo lên được những lớp đối tượng năng động.

Chủ đề thứ hai, hay mục tiêu thứ hai cho C#, là “cùng tiến hóa” với Visual Basic. Cùng tiến hóa, nhưng vẫn giữ những đặc tính riêng biệt. Nói một cách khác, 2 ngôn ngữ sẽ cùng có chung những chức năng và hiệu năng, nhưng vẫn là 2 ngôn ngữ riêng biệt với những cú pháp riêng biệt.

Những chức năng mới của C# được chia ra làm 4 thành phần, như sau:

1. Truy vấn năng động (dynamic lookup)
2. Tham số tên và tham số tuỳ chọn (Named and option parameters)
3. Chức năng giao tiếp với những COM đã được lựa chọn
4. Biến dạng (variance)


Truy vấn năng động (dynamic lookup)
Truy vấn năng động là những chức năng có thể tạo dựng được những hàm, những toán tử và chỉ mục, những thuộc tính và trường truy cập, và những đối tượng sự-tác có thể vượt qua những quy tắc đòi hỏi chỉ định dạng trước khi được khởi tạo.

Truy vấn năng động cho phép một phần mềm có thể kích hoạt được những đối tượng trong lúc vận hành mà không phải lưu tâm đến việc những đối tượng đó thuộc về những dạng nào, và từ đâu tới( COM, HTML DOM, Python, hoặc đối xứng). Chỉ cần áp dụng những thao tác xử lý vào một đối tượng, và để cho bộ vận hành thẩm định những thao tác đó.

Chức năng này cho các bạn sự uyển chuyển và giản dị hóa mã nguồn trong một thảo chương, nhưng đổi lại, dạng của một đối tượng không được thẩm định trong những thao tác truy vấn. Lớp đối tượng năng động không được thẩm tra khi biên lập, do đó, nếu có những lỗi lầm, những lỗi lầm đó chỉ xảy ra khi vận hành. Nói một cách khác, phần mềm của các bạn có nhiều hy vọng bị treo trong khi vận hành. Thông thường, khi phần mềm bị treo vì những lý do có liên quan đến việc xử lý của một đối tượng năng động, sẽ không có gì tổn hại đến hệ điều hành. Nhưng đôi khi, những lỗi lầm này có thể ảnh hưởng đến tính chất bảo vệ hệ thống phần mềm. Do đó, C# cho các bạn có sự tùy chọn giữa năng động và không năng động trước khi khởi tạo một đối tượng.

Dạng năng động (dynamic type)

Với C# 4.0, một dạng tĩnh có thể định dạng năng động. Với dạng tĩnh năng động, các bạn có thể tạo dựng những thao tác với những điều kiện chỉ có thể có trong lúc vận hành:

Code:
Dynamic năngĐộng = GetDynamicObject(...); năngĐộng.M(7);

Với 2 hàng mã nguồn mẫu trên, biên trình csc.exe không thể thẩm định tên và những tham số thuộc đối tượng năngĐộng trên. Do đó, các bạn có thể dùng bất cứ tên (cho thuộc hàm) gì, và bất cứ một tham số nào. Khi phần mềm được vận hành, bộ vận hành DLR mới có thể thẩm định năngĐộng thuộc đối tượng gì. năngĐộng có thuộc hàm M() không, và thuộc hàm năngĐộng.M() có phải là một thuộc hàm có một tham số thuộc dạng số không.

Các bạn có thể gán bất cứ một giá trị nào cho một đối tượng năng động, và một đối tượng năng động cũng có thể gán cho bất cứ một dạng đối tượng nào, như sau:

Code:
class Program {
static void Main(string[] args) {
dynamic d = 199; int i = d; string str = d; Form frm = d;
}
}



Vận hành năng động

Không những chỉ có thuộc hàm có thể...năng động, mà tất cả những gì thuộc về truy cập đều có thể năng động, kể cả uỷ nhiệm:

Code:
dynamic d = 199; d.f = d.P; // truy cap thuoc tinh d["Hai"] = d["Ba"]; // truy van / cap nhat voi chi muc
int i = d + 3; // dung toan tu string s = d(5,7); // Goi nhu mot uy nhiem

Khi vận hành, thao tác xử lý năng động được kích hoạt tuỳ theo tính tự nhiên của những đối tượng năng động dưói đây:

Đối tượng COM

Nếu đối tượng năng động là một đối tượng được định nghĩa từ một linh kiện COM, những thao tác xử lý được gửi qua IDispatch của đối tượng COM đó. Điều này cho phép chương trình gọi những hàm của nhiều dạng COM không có PIA (Primary Interop Assembly), và lệ thuộc vào những chức năng của COM không có trong ngôn ngữ C#, chẳng hạn như thuộc tính chỉ mục, hoặc thuộc tính mặc định.

Đối tượng năng động (dynamic objects)

Nếu đối tượng năng động là một đối tượng năng động thuộc dạng IDynamicObject, thao tác xử lý sẽ được khởi động tại tầng đối tượng. Do đó, một đối tượng định dạng IDynamicObject có thể hoàn toàn thay đổi phương tiện của những thao tác vận hành. Điều này rất thông dụng trong những ngôn ngữ năng động như IronPython hoặc IronRuby. Đối tượng thuộc dạng IDynamicObject còn có thể được dùng bởi HTML DOM.

Đối tượng lớp thuộc về .NET

Nếu không thuộc 2 đối tượng trên, thì đó là một đối tượng lớp .NET thông thường, và những thao tác xử lý được vận hành bằng cách dùng đối xứng (reflection) trên dạng lớp của đối tượng (để tìm ra những dẫn chứng), thí dụ như:

Code:
public void DoiTuongNangDongNET() {
dynamic d1 = new TiepThiVien(“TT001”);
dynamic d2 = new NhanCong(“NC001”);
string s;
d1.M(s, d2, 3, null);
}

Vì hàm M() được gọi từ tầng đối tượng dynamic, biên trình sẽ không thẩm định ngữ nghĩa của hàm M(), mà chỉ lưu giữ thông tin M(2,d2,3,null) cho đến khi vận hành, nhường quyền thẩm định cho bộ vận hành DLR của .NET. Những thông tin này chủ yếu có những ý nghĩa như sau:

“Khởi động hàm M() với những tham số”:
1. Chuỗi ký tự
2. đối tượng năng động (d2)
3. hằng số 3
4. null

Khi vận hành, vì d1 không phải là một đối tượng COM, cũng không được định dạng IDynamicObject, nên bộ vận hành dùng phép đối xứng để truy vấn những dẫn chứng của đối tượng d1 như sau:

Phép đối xứng được dùng để lấy thông tin về 2 đối tượng d1 và d2 và biết được d1 thuộc dạng TiepThiVien, và d2 thuộc dạng NhanCong.
Tìm thuộc hàm M() có dấu ký (string, NhanCong, int, object).
Nếu tìm thấy thuộc hàm, M() sẽ được kích hoạt. Nếu không, lỗi sẽ được ném về hàm DoiTươngNangDongNET().

Lý giải cho những tham số thuộc dạng dynamic (năng động)

Ngay cả trường hợp đối tượng nhận được hàm gọi là một đối tượng thuộc dạng lớp đã được định nghĩa, thông tin về hàm được gọi vẫn được lý giải khi vận hành. Điều này xảy ra nếu hàm được gọi có một hay nhiều tham số thuộc dạng dynamic:

Code:
public void DoiTuongNangDongNET() {
TiepThiVien d1 = new TiepThiVien(“TT001”);
dynamic d2 = new NhanCong(“NC001”); s
tring s;
d1.M(s, d2, 3, null);
}

Trong hàm mẫu trên, tuy d1 là một đối tượng lớp thuộc dạng TiepThiVien, nhưng thuộc hàm M() của nó có một tham số được định với dạng dynamic. Do đó, kết quả vẫn là một dạng năng động, và sẽ được biên lập để được xử lý bởi bộ vận hành DLR theo mô hình năng động.
Những giới hạn của việc dùng đối tượng năng động
Bộ vận hành DLR có những giới hạn dưới đây:

Đối tượng năng động có thể được khởi tạo cho một dạng lớp, nhưng C# 4.0 vẫn chưa có những cú pháp hổ trợ cho việc này.
Bộ vận hành DLR không có khả năng tìm thấy những hàm nới rộng. Do đó, chương trình sẽ gặp lỗi vận hành nếu gọi hàm nới rộng trên một tầng đối tượng năng động.
Hàm vô danh không thể dùng như một tham số khi gọi một hàm trên tầng đối tượng năng động.

Tham số tên và tham số tuỳ chọn

Tham số tên và tham số tuỳ chọn là 2 chức năng khác nhau, nhưng thường được dùng với nhau. Tham số tùy chọn cho các bạn sự lựa chọn dùng hoặc không dùng tham số đó khi gọi một hàm có tham số tùy chọn, trong khi tham số tên là phương pháp để đưa một tham số qua một hàm bằng cách dùng tên của tham số thay vì dùng vị thế của tham số đó theo thứ tự từ trái qua phải.

Có nhiều API, đặc biệt là những linh kiện COM như Microsoft Office API, đã được viết để cung cấp những hàm dùng tham số tên và tham số tùy chọn. Hiện tại (khi chưa có phiên bản C# 4.0), một lập trình C# gặp phải rất nhiều khó khăn khi muốn gọi những hàm có tham số tên và tham số tuỳ chọn. Đôi khi, phải gọi một hàm có hơn 30 tham số, và phải đưa qua hơn 30 tham số đó, thay vì chỉ đưa qua những tham số tuỳ chọn bằng cách dùng tên của tham số.

Và ngay cả những hàm được định nghĩa trong những lớp đối tượng mà các bạn đã tạo lên, muốn gọi những hàm đó, phải đưa qua đầy đủ những tham số thích hợp đã được định nghĩa.

Tham số tuỳ chọn (optional parameters)

Muốn định nghĩa một hàm có những tham số tuỳ chọn, các bạn cần phải cho những tham số đó một giá trị mặc định, như sau:

public void HamThamSoTuyChon(int I1, int I2 = 0, bool b1 = true){}

Trong hàm mẫu trên, hai tham số I2 và B1 là những tham số tuỳ chọn, và không bắt buộc phải dùng khi gọi hàm HamThamSoTuyChon():

Code:
HamThamSoTuyChon(5); // Gọi với 1 tham số HamThamSoTuyChon(5,10); // Gọi với 2 tham số
HamThamSoTuyChon(5,10, false); // Gọi với tất cả tham số

Tham số tên (dùng với tham số tùy chọn)

C# 4.0 không hổ trợ cú pháp không dùng tham số tùy chọn có vị thế ở chính giữa bằng cách dùng những dấu phảy như sau:

Code:
HamThamSoTuyChon(5,, false); // Gọi với 2 tham số 1 và 3 (không được hổ trợ)

Cú pháp như trên, nếu được hổ trợ, sẽ đưa đến hậu quả nhầm lẫn và khó đọc nếu có hàng chục dấu phảy khi gọi một hàm. Các bạn sẽ khó nhận ra tham số nào đã được dùng, và tham số nào đã không được dùng. Với tham số tên, các bạn có thể chỉ định tham số tuỳ chọn khi gọi một hàm có nhiều tham số tùy chọn, như sau:
Code:
HamThamSoTuyChon(5,B1: false); // Gọi với 2 tham số 1 và 3
HamThamSoTuyChon(5,B1:false,I2:10 ); // Gọi với 3 tham số, nhưng không theo thứ tự

Với cú pháp được hổ trợ trên, khi gọi một hàm có nhiều tham số tùy chọn, các bạn có thể chỉ định tham số được dùng bằng cách dùng tên của tham số đó. Không cần phải lý giải thêm, chắc chắn các bạn đã thấy sự dễ dàng cho người viết, và sự dễ hiểu cho người đọc cho những cú pháp này.

Lý giải vận hành trên những hàm nạp chồng

Tham số tên và tham số tùy chọn, khi được dùng để gọi những hàm nạp chồng, dĩ nhiên, ảnh hưởng đến bộ vận hành .NET, nhưng thật ra rất giản dị khi bộ vận hành phải lý giải một hàm được gọi.

Dấu ký sẽ được dùng nếu tất cả những tham số đã dùng đều là những tham số tuỳ chọn, hoặc tất cả đều có tên, hoặc tất cả đều nằm theo vị thế đã được định nghĩa.

Luật “chính-xác-hơn” (betterness) sẽ được dùng cho những tham số được chỉ định (và bác bỏ những tham số tuỳ chọn).

Nếu 2 dấu ký bằng nhau, dấu ký nào có tất cả tham số sẽ được chọn. Thí dụ như, nếu các bạn đã có 4 hàm nạp chồng M(...) được định nghĩa như sau:
Code:
M(string s, int i = 1) {

}

M(object o) {

}

M(int i, string s = “Chào”) {

}

M(int i) {

}

Và mã nguồn mẫu dưới đây gọi hàm M()
M(5);

Trong đoạn mã mẫu trên, các bạn có thể nhận ra, M(string 2, int i=1) không được dùng, vì 5 là một hằng số không thể nào chuyển hóa (suy định) qua dạng string. M(int I, string s = “Chào”) có thể được dùng vì tham số thứ 2 là một tham số tùy chọn. M(int i) cũng có thể được dùng.

Nhưng sau cùng, M(int I) sẽ được dùng để gọi, vì không có tham số tùy chọn.

Chức năng cho COM interop

Đây có lẽ là một chức năng sẽ được rất nhiều người ưa thích. Hãy nghĩ đến việc các bạn có thể dùng những gì sẵn có trong Exel để hiển thị những dữ liệu trong CSDL của bạn như một bảng Exel thường dùng ở các văn phòng, và có thể hiển thị những đồ họa (graphs) đẹp mắt được người xử dụng ưa chuộng.

Nhập khẩu năng động (dynamic import)

Các bạn có thể dùng từ khóa using để nhập khẩu một linh kiện COM (được hổ trợ), và sau đó khởi tạo một đối tượng Exel để dùng trực tiếp (thay vì những cách dùng kiểu ép dạng cũ):

Code:
excel.Cells[1, 1].Value = "Chào" // Thay vì ((Excel.Range)excel.Cells[1, 1]).Value2 = "Chào";
Excel.Range range = excel.Cells[1, 1];
// Thay vì Excel.Range range =(Excel.Range)excel.Cells[1, 1];


Vận hành không cần tới PIA (Program Interop Assemblies)

PIA là những linh kiện .NET có kích thước lớn được tạo dựng từ những linh kiện COM để có thể khởi tạo những dạng vững mạnh (được định nghĩa trong linh kiện COM) khi dùng với một lập trình C#. PIA cung cấp những hổ trợ tốt đẹp khi các bạn thiết kế một phần mềm. Đổi lại, trong lúc vận hành, những linh kiện có kích thước lớn này, khi được đưa vào bộ nhớ, có những tác dụng không tốt đến phần mềm của các bạn. Không những thế, lại là nguyên nhân có thể làm cho phần mềm của các bạn không thể vận hành vì lý do không có phiên bản COM thích hợp.

Chức năng no-PIA (không cần tói PIA) cho phép phần mềm của các bạn tiếp tục dùng PIA trong lúc thiết kế, nhưng không cần tới PIA khi vận hành. Thay vì đó, biên trình csc.exe đưa thẳng những phần đã được dùng từ PIA vào phần mềm của các bạn.

Loại bỏ tham số dạng tham chiếu (ref)

Nhiều linh kiện COM có những hàm nhận những tham số có dạng ref (tham chiếu). Không giống như tham số dạng tham chiếu của C#, dạng tham số tham chiếu của COM vẫn là những tham số có giá trị thực.
Do đó, C# 4.0 sẽ loại bỏ tất cả những dạng tham chiếu khi gọi một hàm của COM bằng cách tạo những biến từ tạm thời để lưu giữ giá trị của những tham số, và dùng những biến từ đó khi vận hành.

Hổ trợ dạng khả biến (variance)

Trong chương III - 10, các bạn đã được hướng dẫn về những dạng tập hợp chung mẫu (System.Collections.Generic). Các bạn có thể sẽ ngạc nhiên, khi biết, hàng mã nguồn thứ 2 dưới đây là một hàng mã nguồn có lỗi biên lập:

Code:
IList mangChuoi= new List(); IList mangDoiTuong = mangChuoi; // Lỗi biên lập IEnumerable mangDoiTuong2 = mangChuoi; // Lỗi biên lập

Hàng mã nguồn trên bị lỗi, vì biến từ mangChuoi đã không được định nghĩa đồng dạng với mảngDoiTuong. C# không hổ trợ sự chuyển dạng trên, vì có lý do rất chính đáng, vì hai biến từ mảng trên có thể được thao tác nhầm lẫn như sau:

Code:
mangDoiTuong[0] = 5.15d; string strTest = mangChuoi[0];

Một đối tượng dạng Object có thể lưu giữ một giá trị dạng double, nhưng một chuỗi ký tự thì không thể. Mặc dù một đối tượng dạng Object có thể lưu giữ một giá trị dạng chuỗi ký tự, nhưng khi có những gán ghép giá trị giống như những đoạn mẫu trên, chương trình sẽ bị lỗi vận hành.

Tuy nhiên, nếu những mảng tập hợp trên được dùng với dạng khả biến (variance), mã nguồn sẽ không bị lỗi biên lập.

Dạng đồng biến (covariance)

Với C# 4.0, giao ước IEnumerable sẽ được định nghĩa với cú pháp và ngữ nghĩa như sau:

Code:
public interface IEnumerable : IEnumerable {
IEnumerator GetEnumerator();
}

public interface IEnumerator : IEnumerator {
bool MoveNext();
T Current { get; }
}

Chỉnh từ out trong những định nghĩa trên chỉ định tham số dạng T chỉ có thể xảy ra trong điểm ra của giao ước, nếu không, sẽ nhận được lỗi biên lập. Đổi lại cho sự giới hạn này, giao ước IEnumerable trở thành một giao ước có tham số dạng đồng biến ở điểm giữ chỗ , có nghĩa là IEnumerable có thể coi là IEnumerable nếu X có định nghĩa dùng để chuyển hóa dạng.

Chức năng này rất hữu dụng cho nhiều hàm của LINQ, sẽ được hướng dẫn trong chương kế tiếp.

Dạng nghịch biến (contra-variance)

Một giao ước tập hợp chung mẫu cũng có thể có tham số dạng thuộc dạng nghịch biến. Tham số dạng thuộc dạng nghịch biến được định nghĩa với chỉnh từ in, như sau:

Code:
public interface IComparer { public int Compare(T trái, T phải); }

Giao ước chung mẫu, hoặc uỷ nhiệm chung mẫu, còn có thể có những tham số dạng thuộc dạng đồng biến và nghịch biến, như sau:

Code:
public delegate TResult Func(TArg arg);

Giới hạn

Tham số dạng khả biến chỉ có thể định nghĩa cho giao ước và uỷ nhiệm, và dạng khả biến chỉ có thể áp dụng cho những lớp đối tượng tham chiếu có hổ trợ chuyển hóa dạng. Chẳng hạn như chuyển hóa dạng giữa NhanVien và NhanCong, hoặc NhanCong qua Object. Từ int, hoặc double qua object chỉ là đóng gói, không phải là chuyển dạng, vì int và double không phải là những dạng tham chiếu, mà là những dạng có giá trị thực.

Mã nguồn mẫu

Dưới đây là nguyên văn bản mã nguồn mẫu, với Exel và Word được dùng để khởi tạo 2 đối tượng năng động. Sau đó, là những thao tác xử lý trên 2 đối tượng. Không có gì đặc biệt để phải lý giải, ngoài mục đích trình bày những chức năng mới của C# 4.0(dễ đọc, dễ hiểu hơn những cú pháp dùng COM trong những phiên bản trước).

Code:
using System; using System.Diagnostics;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;

class Program {
static void Main(string[] args) {
var excel = new Excel.Application();
excel.Visible = true;
excel.Workbooks.Add(); // tham số tùy chọn không được đưa qua
excel.Cells[1, 1].Value = "Process Name"; // không cần ép dạng, vì Value là variance
excel.Cells[1, 2].Value = "Memory Usage"; //
var processes = Process.GetProcesses() .OrderByDescending(p => p.WorkingSet) .Take(10);
int i = 2;
foreach (var p in processes) {
excel.Cells[i, 1].Value = p.ProcessName; // không cần ép dạng
excel.Cells[i, 2].Value = p.WorkingSet; // không cần ép dạng
i++;
}
Excel.Range range = excel.Cells[1, 1]; // không cần ép dạng
Excel.Chart chart = excel.ActiveWorkbook.Charts. Add(After: excel.ActiveSheet); // dùng tham số tên và tham số tuỳ chọn
chart.ChartWizard(Source: range.CurrentRegion, Title: "Memory Usage in " + Environment.MachineName); //tham số tên (Title) và tùy chọn
chart.ChartStyle = 45;
chart.CopyPicture(Excel.XlPictureAppearance.xlScreen, Excel.XlCopyPictureFormat.xlBitmap, Excel.XlPictureAppearance.xlScreen);
var word = new Word.Application();
word.Visible = true;
word.Documents.Add();
word.Selection.Paste();
}

Jun 6, 2010

Những tích lũy thú vị về .NET

Lang thang lướt web tìm đc bài viết khá hay bên trang ApTech đem về post lại ở đây, Trong này có nhiều điều đã biết rồi nhưng tôn trọng tác giả mình vẫn giữ nguyên theo bản gốc.

Bài viết này trình bày một số kiến thức về .NET mà các lập trình viên cần nắm được để phục vụ cho công việc của mình được tốt hơn.

1. Sự khác nhau giữa các lớp Trace và Debug? - Trace dùng để theo dõi các hành động xảy ra. Nó hoạt động trong các đóng gói cả Debug lẫn Release. Trace là khả năng của chương trình tự đưa ra các thông tin về hành động của mình. - Debug dùng để tìm và sửa các lỗi trong chương trình. Nó chỉ hoạt động trong đóng gói Debug.

2. Sự khác nhau giữa static readonly và const? - Static readonly là hằng số được khởi tạo khi thực thi chương trình. - Const là hằng số được khởi tạo khi biên dịch chương trình.

3. Sự khác nhau giữa String và StringBuilder? - String là lớp không thay đổi. Mọi phương thức sẽ tạo ra một biến String mới. - StringBuilder là lớp thay đổi. Các phương thức của biến sẽ ảnh hưởng đến đến biến StringBuilder hiện tại.

4. Sự khác nhau giữa “” và String.Empty? - “” sẽ tạo thêm 1 đối tượng khi làm việc với nó (so sánh, copy…) - String.Empty không tạo đối tượng nào cả. String.Emtpy nằm trong mscorlib. Khi kiểm tra 1 String có rỗng hay không nên dùng String.Length == 0 để có tốc độ nhanh nhất.

5. Có thể gán một struct bằng null hay không? - Có thể nếu bạn lập trình với C# 2.0. Ví dụ: int? var = 1; var = null; 6. Sự khác nhau giữa == và phương thức Equals? - == so sánh theo kiểu giá trị. - Equals so sánh theo kiểu tham chiếu.

7. Sự khác nhau giữa throw và throw ex? - throw đế đưa lại toàn bộ các tầng theo dõi của lỗi ra. - throw ex bỏ bớt các tầng theo dõi bên dưới phương thức gọi throw ex.

8. Connection Pooling dùng để làm gì? - Cho phép tăng tốc độ của các ứng dụng Web bằng cách dùng lại các kết nối thay vì tạo các kết nối mới với mỗi yêu cầu.

9. .NET có hỗ trợ thừa kế từ nhiều lớp hay không (multiple inheritance)? Tại sao? - Không. Vì sẽ không hiểu được khi gọi 1 phương thức mà 2 lớp cha cùng override nó.

10. Sự khác nhau giữa abstract class và interface? - Có thể thừa kế từ nhiều interface nhưng chỉ có thể thừa kế từ 1 abstract class. - Có thể viết sẵn các thực thi trong Abstract class, nhưng interface thì không. - Interface dùng để gom các hành động cần được hiện thực , các khả năng của một đối tượng (ví dụ con người và xe cộ cùng có khả năng đi lại, nhưng con người không cùng tính chất với xe cộ), còn abstract class cho các lớp thừa kế cùng 1 loại, tính chất hay trạng thái (ví dụ đàn ông, phụ nữ, trẻ con, người già đều là con người). - Abstract class có tốc độ thực thi nhanh hơn interface. - Thêm 1 tính năng mới vào interface sẽ phá vỡ toàn bộ các lớp hiện thực, còn abstract thì không.

11. Hàm GetHasCode() trong System.Object dùng để làm gì? - Trả về giá trị của một đối tượng. Chú ý hàm này mặc định không trả về giá trị duy nhất hoặc không đổi. Hàm này có thể override.

12. Sự khác nhau giữa DataSet và DataReader? - DataSet có thể đọc và ghi trong khi DataReader chỉ có thể đọc. - DataSet có thể chứa nhiều bảng còn DataReader chỉ có thể chứa 1 bảng. - DataSet làm việc ở chế độ không kết nối còn DataReader làm việc ở chế độ kết nối. - DataSet có thể di chuyển tới và trở lại còn DataReader thì chỉ có thể di chuyển tới. - DataSet truy cập chậm hơn DataReader.

13. Sự khác nhau giữa các phuơng thức Copy và Clone? - Clone chỉ copy cấu trúc trong khi Copy copy cả cấu trúc lẫn dữ liệu.

14. Sự khác nhau giữa Dispose, Destructor và Finalize? - Destructor sẽ được chuyển thành Finalize khi biên dịch. Hàm Finalize được gọi bởi .NET Runtime và chúng ta không thể đoàn được nó được gọi khi nào, nhưng nó chắc chắn sẽ được gọi. - Dispose sẽ giải phóng bộ nhớ ngay khi nó được gọi. Lưu ý nếu lớp nào override Dispose mà quên gọi thì các đối tượng sẽ không tự giải phóng bộ nhớ.

15. Serialization là gì? - Là sự chuyển chuyển đối tượng thành 1 luồng các bytes.

16. Sự khác nhau giữa XmlSerializer, BinaryFormatter và SoapFormatter? - XmlSerializer dùng cho dịch vụ Web. - BinaryFormatter/SoapFormatter dùng cho Remoting. - SoapFormatter dùng để tuần tự hóa 1 đối tượng thành SOAP. - BinaryFormatter dùng để tuần tự hóa 1 đối tượng thành dạng nhị phân. - XmlSerializer chỉ chuyển đổi các tính chất public còn BinaryFormatter/SoapFormatter chuyển đổi cả public lẫn private.

17. Sự khác nhau giữa overriding và shadowing? - Overriding cung cấp sự hiện thực mới của 1 hàm ở lớp thừa kế nhưng không thay đổi số biến, kiểu trả về, mức truy cập còn shadowing thì có thể thay đổi (từ khóa new trong C#).

18. Sự khác nhau giữa class, object, struct và interface? - Class là cấu trúc dữ liệu định nghĩa bởi người dùng chứa các tính chất và phương thức. Object là một trường hợp cụ thể của class. Class không chiếm bộ nhớ, còn Object được tạo trong bộ nhớ. - Class là cấu trúc dữ liệu định nghĩa bởi người dùng chứa các tính chất và phương thức. Struct là kiểu giá trị được lưu trữ trong stack còn class là kiểu tham chiếu (các object) được lưu trữ trong heap. - Khi struct được khởi tạo không bằng hàm khởi tạo người dùng sẽ phải khởi tạo tất cả các Fields trước khi sử dụng nó. - Interface là một hợp đồng gồm một nhóm các phương thức cần được hiện thực.

19. Sự khác nhau giữa Property và Field? - Property dùng để quản lý sự truy cập đến Field. Dùng Property để đảm bảo Field không bị gán các giá trị không hợp lệ.
(linhdkl: còn nhớ vấn đề này có đồng chí bên congdongcviet có tranh luận với mình đồng chí ấy cho rằng 2 khái niệm là là một, nhưng thực chất đây là 2 vấn đề khác nhau giống như kiểu người thật và bí danh vậy ... )

20. Sự khác nhau giữa static Method, static constructor với method và constructor thông thường? - Static method có thể gọi mà không cần khởi tạo biến. Static constructor chỉ được gọi đúng một lần khi object đầu tiên được khởi tạo.

21. Các biến tĩnh và chỉ dẫn chương trình được lưu ở đâu? - Ở 1 vùng bộ nhớ đặc biệt gọi là Permanent Storage area.

22. Sự khác nhau giữa stack và heap? - Stack và heap là các vùng bộ nhớ. Heap nằm giữa stack và Permanent Storage area, và độ lớn có thể thay đổi khi thực thi chương trình.

23. Sự khác nhau giữa Boxing and Un-Boxing? - Boxing là chuyển đổi kiểu giá trị thành kiểu tham chiếu. Un-Boxing ngược lại. 24. Mục đích của thừa kế (inheritance)? - Để tái sử dụng.

25. Mục đích của đa hình (poymophism)? - Một hành động có thể xảy ra theo nhiều cách khác nhau.

26. Sự khác nhau giữa Compile Time Polymorphism và Run Time Polymorphism? - Compile Time Polymorphism - ví dụ Overloading, một hàm có thể có nhiều cách biểu diễn. - Run Time Polymorphism - ví dụ Overriding, một hàm có thể có nhiều cách xử lý.

27. Sự khác nhau giữa delegate và event? - delegate là một lớp (class) đại diện cho hàm con trỏ kiểu an toàn hoặc hàm gọi (call backs) chỉ đến địa chỉ tham chiếu của một (hay nhiều) hàm. Con trỏ hàm chứa trong delegate được gắn vào một đối tượng đích (target) và khi delegate được kích hoạt phương thức sẽ được gọi ở đối tượng đích. Sự hữu ích của delegate không nằm ở chỗ giữ địa chỉ tham chiếu của các hàm mà để định nghĩa và dùng các tên hàm khi runtime thay vì compile time. - event cho phép xác định một delegate sẽ được gọi khi có sự xuất hiện của “sự kiện” nào đó. event là một modifier trong khi delegate là một lớp. event cho phép một delegate được khai báo trong interface.

28. Mất đâu mất mục 28 rồi ta. ???

29. AppDomain là gì? - Là một miền riêng biệt lưu trữ code và dữ liệu cho một application. Một process có thể chứa nhiều AppDomains. Khi bạn copy một DLL mới vào bin, ASP.NET runtime sẽ không thể đưa nó vào một AppDomain đang chạy.Nó sẽ dừng từ từ AppDomain cũ (dừng hẳn khi nó dừng tất cả các requests) và mở một AppDomain mới.

30. Sự khác nhau giữa publish và published interfaces. - publish interface là interface mà bạn có thể sửa tất cả những code nào dùng nó còn published interface là interface mà bạn không thể sửa code dùng nó.

31. Sự khác nhau giữa try{}catch{} và try{}catch{Exception ex}? - Chúng giống hệt nhau.

32. Sự khác nhau giữa 1/0; và try{1/0;} catch {throw;} - Chúng giống hệt nhau. Vì vậy nếu không xử lý catch thì đừng catch.

33. Sự khác nhau giữa Remoting và Web service? - Web service không có trạng thái, không cần biết đến client chỉ sử dụng trên HTTP, hỗ trợ không đồng nhất các môi trường, tốc độ chậm hơn Remoting. - Remoting có trạng thái kết nối, hỗ trợ nhiều giao thức hơn HTTP, TCP…, đòi hỏi môi trường đồng nhất, tốc độ nhanh đặc biệt khi dùng trên TCP.

34. Sự khác nhau giữa error và exception? - Error là lỗi của chương trình còn exception là lỗi chương trình được phát hiện và có thể xử lý.

35. Sự khác nhau giữa Procedure và OO? - Procedure gồm các hàm và các biến, tất cả các hàm đều có thể truy cập đến tất cả các biến. Không thể quản lý các biến. - OO gom hàm và biến vào các đơn vị object. Các hàm và biến được quản lý trong nội bộ object. Các object tương tác với nhau thông qua các interfaces.

36. CLR, CTS, CLS, MSIL, JIT, PE, GAC là viết tắt của những gì? - Là Common Language Runtime: môi trường để chạy các ứng dụng .NET - Là Common Type System: mô tả các loại dữ liệu trong .NET. - Là Common Language Specification: mô tả các quy định và chuẩn cho các ngôn ngữ trong .NET - Là Microsoft Intermediate Language: ngôn ngữ thông dịch của .NET. - Là Just In Time: trình biên dịch MSIL thành mã máy. - Là Portable Executable: file chứa MSIL. - Là Global Assembly Cache: nơi lưu trữ các Asembly dùng chung.

37. Các mâu thuẫn giữa OO và RDBMS? - Cấu trúc cấp bậc trong OO có thể là vô tận trong khi ở RDBMS chỉ có 4 loại table, row, column, cell. - Các đối tượng trong OO bản thân là phân biệt trong khi trong RDBMS cần phải có primary-key. - Các đối tượng trong OO có thể tham chiếu đến nhau rất đơn giản nhưng trong RDBMS thì phức tạp thông qua JOIN - Sự thừa kế trong OO là đơn giản trong khi trong RDBMS hầu như không có khái niệm đó. Một bảng cần chứa tất cả các tính chất, có khi là thừa. - Các đối tượng trong OO có thể có các hành động tác động đến tối tương khác.trong RDBMS thì phức tạp thông qua TRIGGER - Khả năng truy cập trong OO là hạn chế trong khi ở RDBMS là không giới hạn.

38. Sự khác nhau giữa Response.Redirect và Server.Transfer. - Response.Redirect đơn thuần là chuyển bạn đến một trang mới giống như bạn gõ địa chỉ trang đó trên browser và request đến server. - Server.Transfer cũng chuyển bạn đến trang mới nhưng ở phía server, làm giảm request đến server, giữa nguyên URL của bạn và có thể chuyển cả các query string và biến trên form đên địa chỉ mới, chỉ thực hiện giữa các trang trên cùng 1 host.

39. Vai trò của ASPX page và ASPX page code-behind trong MVC. - ASPX page là View còn ASPX page code-behind là Controller.

40. Làm thế nào để try/catch trên toàn bộ 1 ASPX page. - Dùng Page_Error event.

41. Sự khác nhau giữa Cohesion và Coupling - Cohesion là sự liên kết giữa các thành phần trong một module. Một thiết kế tốt nên có sự liên kết giữa các thành phần thật chặt chẽ. - Coupling là sự kết nối giữa các module với nhau. Một thiết kế tốt nên có sự kết nối thật lỏng lẽo giữa các module.

42. Refractoring là gì? - Là sự thiết kế lại cấu trúc của code bằng cách thay đổi cấu trúc bên trong mà không ảnh hưởng đến các hành vi bên ngoài (interface) của đoạn code (module, system) đó.

43. Phân biệt HttpApplication, Session, ViewSate và HttpContext? - Cả 4 thành phần trên đều dùng để lưu dữ liệu của một Web Application. - HttpApplication có tác dụng trong toàn bộ quá trình thực thi của Web Application. - Session có tác dụng trong 1 lần ghé thăm (visit) của người dùng. Nó kết thúc khi gặp timeout. - ViewState có tác dụng trong trong 1 trang web. - HttpContext có tác dụng trong 1 request.

_____ST_____

Mar 16, 2010

Sử lý đệ quy trong SQL Server

Hôm nay làm môt tut về đệ qui trong SQL server. Trong lập trình thông thường bạn sẽ phải sử lý nhiều tình huống đề quy, nhưng ít khi nó thể hiện rõ tính chất đệ quy bởi nó chỉ là vòng lặp dạng for hoặc while. Và thực ra việc thiết kế giải thuật người ta cũng cố gắng đề giải đệ quy hoặc khử đệ quy để bảo đảm cấu trúc bộ nhớ của trương trình cũng như là cho code dễ hiểu.
Nhưng không phải lúc nào như lý thuyết cũng là đúng, trong một số tình huống cụ thể cách đệ quy chở nên hiệu quả ngắn ngọn và tối ưu hơn cách viết thông thường. Vậy bài viết này hướng dẫn bạn đệ quy trong DB.

Đệ quy để làm gì ? Với một business phức tạp và sử lý trên một cấu trúc cây đa cấp bạn sẽ mắc phải vấn đề rác rối về hiệu xuất của hệ thống khi quyết định sử lý tất cả trên tầng business. Chính vị vậy bạn cần sử lý một số các nghiệp vụ cụ thể trong DB nhằm tăng tốc cho hệ thống của mình. Đây chính là mảnh đất mà chúng ta khai thác...

Giả sử bạn có một cây đa cấp chông nó như thế này.


Khi đó trong DB bạn sẽ có một cấu trúc như thế này cho cái cây đó

và việc sử lý trên cây sẽ vô cùng rác rối với mỗi một node bạn phải kiểm tra xem nó là có con không ? cha nó là ai ? anh chị em nó là gì ? ....
ở đây tôi chỉ viết một hàm trong DB sql 2005, với mục đích nhận vào một node id và trả về môt bảng các node id con cháu nêu có.

code here.

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[udfNodeChirent]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[udfNodeChirent]
GO

CREATE FUNCTION [dbo].[udfNodeChirent]
--======================================
--created by : linhdkl
--created date : 16/03/2010
--======================================

(
@parentID int
)
RETURNS @tbl TABLE (id int,valu int)
WITH EXECUTE AS CALLER
AS
begin
if @parentID > 0
begin
declare @tempCount int
declare @count int
set @count = 0
select @count = count(id)from tree where parentNodeid = @parentID
if(@count > 0)
begin
insert @tbl(id,valu) select ROW_NUMBER() over( order by ID),id
from tree
where parentNodeid = @parentID
declare @row int
set @row = 1
while @row <= @count
begin
select @tempCount = count(id) from @tbl
select @parentID = valu from @tbl where id = @row
insert @tbl(id,valu) select ROW_NUMBER() over( order by ID) + @tempCount,valu
from dbo.udfNodeChirent(@parentID)
set @row = @row +1
end
end
end
return
end
GO


Ok như vậy mình đã có cái func này và đây là kết quả.

select * from dbo.udfNodeChirent(47)
nó sẽ có kết quả là :

id valu
----------- -----------
1 72
2 99
3 100
4 73
5 74
6 95
7 105
8 106
9 75
10 76
11 102
12 103
13 104
14 107
15 101

(15 row(s) affected)

cái id chính là số thứ tự và valu là id của các con, cháu, chắt của thằng node 47.

Tuy nhiên cũng xin nói thêm là đây chỉ là cách sử lý dựa trên hệ thống đã có sẵn, tức là việc này chỉ cải thiện tình trạng một cách miễn cưỡng. Nếu một hệ thống đc thiết kế tốt, việc sử lý này sẽ sử dụng một danh sách liên kết và sử lý phi tuyến tính sẽ nhanh hơn rất nhiều. Tuy nhiên giá trị của giải thuật đệ qui vẫn tồn tại trong bất kỳ trường hợp nào.

../..


Mar 2, 2010

Cờ toán Việt Nam.

Từ nay người VIỆT NAM chúng ta cũng đã có một môn cờ riêng của người VIỆT bên cạnh cờ tướng của Trung quốc và cờ vua ! Thật tự hào làm sao

“Đứa con” không được thừa nhận

Họ nghi hoặc ông cũng có lý. Bởi vì theo tính toán, tổng số nước đi của cờ toán là lũy thừa của 87. Đó là một con số khổng lồ mà người chơi cờ không bao giờ có thể chơi hết những nước đi khác nhau như vậy. Ủy ban Khoa học nhà nước lúc ấy phải nhờ các chuyên gia của Liên Xô (cũ) tính toán, nhưng họ cũng không tính được kết quả lũy thừa của 87 là bao nhiêu. Do không tính được số nước cờ, người ta không công nhận sản phẩm của ông.

Lòng ông Bẩy nặng trĩu. Ông mang sản phẩm trí tuệ của mình đến một tờ báo dành cho trẻ em, đề nghị báo đăng để học sinh cả nước biết. Báo lên khuôn rồi, chẳng may giáo sư Trần Quốc Vượng (đã quá cố) tình cờ thấy được, liền hỏi biên tập viên là thứ cờ này đã đăng ký bản quyền chưa, nếu chưa thì đừng cho đăng. Bởi ông sợ nếu đăng thì chất xám của ông Bẩy sẽ bị đánh cắp ngay lập tức. Báo lại bóc ra.

Năm 1988, con trai ông Bẩy đi Liên Xô. Ông bảo anh ta mang sang đó dịch ra tiếng Nga để mọi người chơi cho khỏi phí. Nhưng khi đến Cục Xuất cảnh trình bày, anh công an bảo: “Nếu có vấn đề gì thì bác sẽ phạm tội bán tài sản trí tuệ quốc gia”. Ông hoảng quá, lại thôi. Đi bao nhiêu cơ quan, cơ quan nào cũng từ chối mà ông cũng không biết phải đem trình cơ quan nào.

Món cờ của ông đành phải cất vào ngăn tủ, cho đến khi nghe Nhà nước thành lập một cơ quan chịu trách nhiệm về bản quyền, ông Bẩy lại hớn hở đem cờ toán đi trình làng, định là lần cuối, không được thì thôi. Thật bất ngờ, tháng 5-2005, Cục Bản quyền tác giả văn học nghệ thuật (Bộ VH-TT) chính thức công nhận sản phẩm trí tuệ do ông nghĩ ra. Ông Bẩy vui như đào được vàng ròng, hóm hỉnh bảo: “Sau 20 năm, “con” tôi mới được “cấp giấy khai sinh”. Thế là cờ toán đã có bản quyền, không sợ bị ai đánh cắp”.

Ngay sau khi món cờ toán của ông được cấp bản quyền, một tờ báo ở Hà Nội đã đặt vấn đề bán đấu giá sở hữu trí tuệ với giá khởi điểm là 1 triệu USD. Biết tin này, một chuyên gia về cờ ở Trung Quốc đã thuê phiên dịch viên tìm đến tận nhà ông ở Bắc Ninh, đề nghị trả 1 triệu USD để mua lại bản quyền và nói rằng sẵn sàng trả hơn nếu có người khác trả nhiều hơn. Tuy nhiên, ông Bẩy không chấp nhận bởi điều kiện của chuyên gia người Trung Quốc đưa ra là phải thay các dấu chấm tròn trên mặt quân cờ bằng các chữ: nhất, nhị, tam, tứ, ngũ, lục, thất, cửu.

Đồng thời, phải thay tên “cờ toán VN” bằng cờ toán quốc tế. “Tôi không muốn để người ta thay tên gọi vì khi sáng tạo món cờ này, điều thôi thúc tôi là phải sáng tạo ra một thứ cờ của VN, mang nguồn gốc VN. Tôi cũng không bán bởi họ mua nó với ý định thương mại hóa. Nếu họ mua để phổ biến thì tốt, còn ngược lại tôi cũng chẳng cần. Bao năm nay tôi vẫn sống bằng nghề nặn tượng và vẫn đủ sống” – ông Bẩy bộc lộ quan điểm. Ông nói thêm: “Cái mà tôi cần bây giờ là bằng cách nào, phương tiện ra sao để phổ biến cho nhiều người chơi cờ toán một cách hiệu quả, để tôi khỏi tốn tiền photo các bài hướng dẫn”.

Chuyện là, từ khi món cờ toán của ông được công khai thì mỗi ngày có hàng chục, hàng trăm người ở quanh TP Bắc Ninh và khắp các tỉnh trong cả nước gửi thư, gọi điện cho ông xin được gửi bản photo hướng dẫn cách chơi, luật chơi cờ toán. Ông đã tốn cả bạc triệu để gửi các hướng dẫn cho người hâm mộ nhưng vẫn không xuể.

Mới đây, Sở GD-ĐT tỉnh Bắc Ninh có kế hoạch trình Bộ GD-ĐT đưa món cờ toán của ông vào thành môn học cho học sinh ở Bắc Ninh. Trong tháng bảy này, UBND tỉnh Bắc Ninh dự định mở một hội thảo về cờ toán của ông Vũ Bẩy. Các chuyên gia của Ủy ban Thể dục thế thao VN cũng đã gặp ông và hứa sẽ phát triển môn cờ toán ra cả nước.

Bàn cờ toán do Vũ Bẩy thiết kế, sáng tạo đã được cấp giấy chứng nhận bản quyền tác giả sau 20 năm chờ đợi


Ván cờ trị giá 1 triệu đô la

Cha đẻ của môn cờ thuần Việt này không phải một giáo sư, tiến sỹ mà là một người đàn ông chỉ học hết lớp bảy. Đó là ông Vũ Văn Bảy, trú tại phố Vũ Ninh, thành phố Bắc Ninh. Hiện ông đang sống bằng nghề làm tượng. Nhiều người bất ngờ vì nghe nói đã có người đặt vấn đề mua lại bản quyền của môn cờ này với giá một triệu đô la, nhưng ông Bảy nhất quyết không bán vì một lẽ rất đơn giản: nó phải là môn cờ của người Việt Nam!

Lời đồn đại về bản quyền có giá một triệu đô dẫn chúng tôi đến ngôi nhà của ông Bảy tại thành phố Bắc Ninh. Cái ấn tượng đầu tiên với riêng tôi là tấm biển trưng ở cổng nhà: “3 THẾ HỆ HỌA SỸ- ĐIÊU KHĂC VŨ VĂN BẢY, sáng tác – thi công các công trình nghệ thuật”, la liệt ở ngoài sân là những bức tượng: Phật, lãnh tụ, quan họ, phù điêu… ngôi nhà cũng là xưởng làm việc, và kiêm luôn cửa hàng.

Nó phải là môn cờ của người Việt Nam !

Ông Bảy ra đón chúng tôi trong bộ quần áo “điêu khắc gia”, lấm lem bùn đất. Cách tiếp khách của ông cũng vô cùng đặc biệt, ông nói oang oang từ trong ra ngoài, chẳng cần biết quen hay sơ, cứ nắm tay thật chặt, rồi mời vào nhà như đã biết nhau từ lâu lắm.

Khi nghe chúng tôi muốn hỏi về chuyện cờ toán và lời đồn bản quyền giá một triệu đô, ông Bảy hào hứng hẳn, ông chém tay vào không khí nói rất to: có chứ, có cái thằng người Trung Quốc nó sang tận đây đặt vấn đề mua bản quyền để nó kinh doanh. Nhưng tôi không bán vì nó bảo phải đổi những con cờ mang số 1,2,3… thành nhất, nhị, tam, tứ… Tôi giải tán luôn. Tôi bảo: “…nếu thế thì mất tính Việt Nam à? Toi công tôi mấy chục năm nay à? Cờ của tôi là cờ thuần Việt, không thể để mất cái chất Việt ấy được…”.

Ông Bảy nói đến đây, nhổm cả người lên ghế, giọng căng thẳng: cái môn cờ này tôi không biết giá trị nó như thế nào, nhưng tôi đã nghiên cứu từ lâu lắm. Hồi xưa, nhìn cái trò Ru-bich gì đó của bọn Tây – cái trò hình vuông xanh xanh đỏ đỏ ấy, nó đơn giản thế mà cuốn hút cả hành tinh. Ai cũng thích chơi nó vì đơn giản nhưng lại phức tạp, tôi thấy người Việt mình thiệt quá! Trò chơi nào cũng phải “vay” người ta. Các ông cứ nhìn bọn trẻ bây giờ thì biết, suốt ngày cắm đầu vào vi tính chơi Games, chán thì quay sang đua xe, chơi bời, thác loạn… Còn những trò chơi dân gian lại không cuốn hút được chúng nó. Mà các ông lên miền núi xem, bọn trẻ ở đó thiệt như thế nào. Suốt ngày chỉ quanh quẩn chân núi, bờ sông, cõng nhau ngẩn ngơ nhìn trời đất… tội lắm! Cứ nghĩ đến cái trò ru bích, ru beo của bọn Tây lại thấy bực. Tôi nhất quyết phải nghĩ ra cái gì để chơi – mà trò chơi ấy phải một trăm phần trăm ma – de – in Việt Nam .

Ông nói hào hứng, át cả tiếng khách khứa, rồi ông chỉ tay lên tường – nơi cái khung kính lồng bên trong là tấm bằng bản quyền do Cục bản quyền Việt Nam cấp. Ông tự hào nói: “Đây là bản quyền của tôi, đã được nhà nước cấp, yên tâm nhé, không thằng nào đụng vào được… tôi không bán, đố thằng nào dám sản xuất!”. Và ông giải thích: cái môn cờ này của tôi ngoài tính trí tuệ ra nó còn chứa đựng trong đó bao nhiêu triết lý. Tôi nói cho các ông biết, cờ của tôi không có tướng, cờ Tàu, cờ Tây đều có tướng – mất tướng coi như thua. Nhưng tôi lại nghĩ trong đời sống, mất thằng tướng này nó thay ngay thằng tướng khác thua sao được, nếu thua hẳn phải là mất dân… mà dân thì là ai? Trong cờ của tôi dân chính là số 0, nếu bắt được số 0 coi như lấy được lòng dân và chiến thắng…

Nói đến đây ông Bảy ngả người thoải mái ra ghế cười mãn nguyện. Khi chúng tôi hỏi về giấy tờ hay một vật chứng cụ thể nào về việc người Trung Quốc kia hỏi mua về bản quyền, ông Bảy nói: “Có chứ, chúng nó thảo hợp đồng toàn tiếng Tây, mà tôi có biết tiếng Tây đâu, nhưng chỉ nghe nó đòi đổi tên cờ thì tôi giải tán ngay, không thèm nói chuyện… bán biếc cái gì. Tôi đâu có dại, ngần này tuổi tôi đâu có dại… Tiền ai chẳng thích, nhưng tôi sợ tiền lắm, nói dại mồm đại họa lúc nào không biết!”. Và ông bảo: nói cho các nhà báo trẻ biết, tôi sống bằng nghề làm tượng, mỗi tháng bán vài pho là sống, con cái đã trưởng thành, hai vợ chồng già của tôi ăn được mấy. Bây giờ sống êm đềm, thỉnh thoảng bạn bè đến vác cờ ra chơi với nhau cho sướng. Tự nhiên một đống tiền rơi vào nhà – đại họa đấy các bạn trẻ ạ! Nói có vẻ vô lý nhưng thật đấy, không tưởng tượng được đâu!

Bây giờ ông lại nhổm hẳn lên ghế, mặt đỏ lự, cái kính lão lệch hẳn một bên. Ông nhoài người sang phía chúng tôi nói: “Một triệu đô là à, mười mấy tỉ tiền ta à, to lắm! Nghe to lắm đấy, nhưng nếu bây giờ tôi phổ biến được nó rộng rãi ra toàn quốc, rồi thì toàn thế giới. Khi chúng nó say cờ này rồi thì… nói cho các ông biết, tôi chỉ việc mua một chút máy móc, sản xuất bàn cờ và bán… quanh năm bán thì thử hỏi thu bao nhiêu tiền? Ấy là nói đến kinh doanh, nhưng không phải thế, cái quan trọng không phải thế, tôi nghĩ ra bàn cờ này đâu phải vì mục đích tiền…”.

Nói đến đây đột ngột ông Bảy quay sang bảo vợ: “Bà nấu cơm nhé, bọn tôi nhậu đấy…”. Rồi ông quay sang chúng tôi cười rất tươi: “Nhậu với tao nhé, trưa rồi còn gì.”

“Triệu phú cờ toán” vẫn sống tằn tiện bằng nghề nặn tượng.

Trong bữa cơm, ông Bảy vẫn nói rất nhiều, ông uống rất khá, mỗi lần nâng chén lên đều bảo cạn nhé. Ông ta có dáng người to lớn, khuôn mặt thuộc kiểu “ngũ trường tướng”, cái gì cũng dài: măt, mũi, tai, miệng… Và ông chỉ vào góc nhà – nơi đang bày những bức tượng dang dở, nói: “Ngày nào, tôi cũng làm tượng, đêm đến muỗi đốt nhiều mệt lắm… cứ nghĩ đến tiền lại muốn bỏ, nhưng lại sợ và tiếc cái môn cờ này.”. Bọn trẻ hàng xóm, từ ngày chúng nó biết chơi thích lắm, mà chúng nó chơi siêu các ông ạ. Tôi đây lắm lúc thua chỏng vó…”. Rồi ông lại giục chúng tôi uống, thỉnh thoảng lại sai khiến bà vợ, giọng rất gia trưởng.

Nhưng tôi hỏi đến điều mong muốn nhất của ông về môn cờ toán này, khuôn mặt đỏ lự của ông trùng xuống, rồi trầm tư: nói thực với các nhà báo trẻ, tôi chỉ mơ cái môn này được phổ biến rộng rãi. Chẳng hạn như hội khỏe phù đổng của tỉnh Bắc Ninh này chẳng hạn, rồi thì trong các nhà trường. Tôi tin với môn cờ toán, bọn trẻ sẽ học được cách từ duy toán học. Mà đã có tư duy của toán học thì sức tưởng tượng nâng cao, nói cách khác tâm hồn chúng sẽ trong sáng, biết làm người… Ai chẳng muốn mình được nổi tiếng, có nhiều tiền, nhưng cái đó với tôi không còn quan trọng nữa, tôi đã hơn bảy mươi rồi: danh vọng, tiền bạc chẳng nghĩa lý gì. Chỉ mong cái môn cờ này được phổ biến rộng rãi và bọn trẻ say nó là được.

Rồi đột nhiên ông Bẩy lại nhổm dậy như cái lò xo, mắt sáng rực à lên: “Tôi có thằng cháu đang làm phần mềm máy tính về môn cờ này đấy. Nó đang rủ tôi đem đi thi trí tuệ Việt Nam , nó bảo ăn giải là cái chắc… Nhưng tôi bảo nó, thi thố quan trọng gì, cứ đưa lên mạng cho chúng nó chơi là tao sướng rồi.”. Ông lại giục chúng tôi uống, mỗi ngụm rượu ông khà lên một tiếng rất khoan khoái, rồi lại trầm ngâm nghĩ về những đứa trẻ miền núi. Tội lắm các nhà báo trẻ ạ! Cả ngày chúng nó chỉ biết cõng nhau ngẩn ngơ nhìn núi đồi, không biết thế nào là chơi…

Câu nói vô tình của ông Bảy làm tôi – kẻ chép lại những dòng này cũng buồn lây. Quả đúng như vậy, ngày bé tôi và đám bạn ở bản làng chẳng biết chơi gì ngoài núi đồi, sông suối. Tôi nhớ rất rõ những buổi chiều chợ phiên. Tôi đã ngồi mãi ở mỏm đá đầu bản, ngẩn ngơ chờ mé đi chợ về. Hồi ấy, trong cái đầu ngờ nghệch của tôi vẫn nghĩ rằng, từ chợ về mé sẽ mua cho tôi một cái gì đó không phải cái bánh, viên kẹo… mà phải là cái gì vui hơn thế. Có thể hồi ấy tôi mong có một món đồ chơi – tôi nghĩ thế.

Và bây giờ, sự nghi hoặc về lời đồn một triệu đô bản quyền cờ toán của ông Bảy, không còn là mục đích tìm hiểu của chúng tôi nữa. Chẳng quan trọng gì, có trả đến trăm triệu đô la cũng thế. Sự thật giả của một triệu đô có lẽ cuốn hút rất nhiều người hiếu kỳ, nhưng có một sự thật – sự thật là bàn cờ toán đã có mặt trên đời, với tổng số nước đi là lũy thừa của 87, ai có thể đi hết ngần ấy nước cờ? Nhưng cũng chẳng cần đi ngần ấy nước, chỉ cần ngồi xuống và say sưa với nó đã thú vị rồi, đấy là một sự thật!

Ông Vũ Bảy – người đang ngồi trước mặt chúng tôi mới quan trọng – sự quan trọng thể hiện ở chỗ ông ta đã nghĩ ra một trò chơi – một niềm vui cho mọi người và do người Việt chính hiệu nghĩ ra. Cái đó quan trọng hơn tất cả. Còn câu chuyện về số tiền một triệu đô có lẽ nên quên đi được rồi.


Ván cờ và triết lý xã hội

“Người Việt từ xưa đến nay vẫn chơi cờ tướng. Nhưng cờ tướng là của người Trung Quốc. Rồi người ta chơi cờ vua. Cờ vua cũng là môn cờ du nhập. Chẳng lẽ chúng ta không có một loại cờ của riêng ta? Lúc đó tôi nghĩ có thể dùng các con số để tính toán cho một ván cờ được không? Thế là tôi bắt đầu bỏ thời gian để nghiên cứu về một thứ cờ gọi là cờ toán, để làm sao khi chơi cờ, người chơi phải vận dụng các kiến thức về toán học, đồng thời nó còn giúp khả năng toán học của người chơi được tốt lên” – ông Bẩy tâm sự.

Nung nấu từ những năm 1970, đến tận những năm 1980 ông mới hoàn thành được luật chơi cờ toán. Từ vị trí xếp quân cho tới giá trị mỗi quân hay cách bắt quân… ông đều phải sửa đi sửa lại hàng chục lần.

Theo ông, để đi một nước cờ toán thì phải vận dụng một trong bốn phép tính: cộng, trừ, nhân, chia. Do phải sử dụng cách chơi phối hợp cả bốn phép tính, nên tổng số nước đi của một ván cờ toán là lũy thừa của 87 (8787). Trong khi đó, tổng số nước đi của cờ tướng chỉ là lũy thừa của 32, còn cờ vua là lũy thừa của 16). Lũy thừa của 87 là một con số mà “không biết bao nhiêu đời người mới có thể đi hết từng ấy nước đi” – ông khẳng định. Cờ toán vừa dân dã, vừa bác học là vì thế.

Ông Bẩy còn gửi vào cờ toán một triết lý nhân sinh: “Khi chơi cờ toán, nó không chỉ giúp người ta tính toán mà còn dạy cho người ta phải biết lẽ sống. Tính cách từng người sẽ được thể hiện qua ván cờ toán. Người tham lam thì chỉ thích cộng, thích nhân. Nhưng cứ nhân, cứ cộng mãi cũng thất bại (thua). Cái đó cũng giống như ở đời: lá lành phải biết đùm lá rách, phải biết chia sẻ cho người khác”.

Đặc biệt, theo ông, cái này mới là độc đáo: quân số 0 (đứng yên một chỗ, không được di chuyển). Tất cả các quân còn lại 1-9 đều có nhiệm vụ công thủ ngang nhau và có một trách nhiệm chung là bảo vệ quân số 0. Trong cờ vua và cờ tướng, khi mất vua hoặc tướng là bị thua. Tuy nhiên, cờ toán lại khác cờ tướng, cờ vua ở chỗ: quân số 0 là dân chứ không phải tướng hay vua, và khi để dân bị đối phương bắt, người chơi sẽ bị thua tuyệt đối.


Luật cờ toán Việt Nam

A Mô tả hình thức bàn cờ và Quân Cờ

Bàn cờ

· Hình chữ nhật, kích thước: 475mm x 365mm.

· Ở hai đầu bàn cờ trong khung hình chữ nhật nằm ngang 315mm x 45mm, mỗi góc bên trái có một lôgô hình tròn, đường kính 35mm. Trong vòng tròn vẽ đồ họa hình khối óc (màu xám trắng), trái tim (màu đỏ tươi), bàn tay (màu vàng). Phần còn lại một đầu có chữ “ CỜ TOÁN VIỆT NAM ” dòng dưới chữ nhỏ hơn: “Tác giả: Vũ Văn Bảy – Thành phố Bắc Ninh”. Đầu đối diện có 6 chữ “ THÂN THIỆN – TRÍ TUỆ – SÁNG TẠO”.

· Phần còn lại của bàn cờ là 385mm x 315mm được chia đểu thành 99 ô vuông (ngang 9 ô, dọc 11 ô) mỗi cạnh 35mm. Ô thứ 5 từ cạnh vào ở hàng ngang thứ 2 từ dưới lên của mỗi bên có dấu chéo (X) giữa ô vuông. (H1)

HÌNH 1 – BÀN CỜ TOÁN VIỆT NAM

Quân cờ

· Hình trụ tròn, đường kính 25mm, cao 10mm. Mỗi bên có 10 quân. Mầu sắc 2 bên khác nhau. Quân số O hình tròn đồng tâm với bề mặt quân cờ, đường kính 20mm.

· Những quân còn lại dùng dấu chấm tròn làm biểu trưng cho dãy số nguyên đơn từ số 1 đến số 9. Quân số 1=1 chấm, quân số 2=2 chấm…quân số 9 = 9 chấm.

· Tên của mỗi quân cờ gọi theo trị số riêng của từng con số (quân một, quân hai… quân chín)(H2)

H2 – QUÂN CỜ TOÁN VIỆT NAM

B Luật chơi

Xếp quân

· Hai bên cùng xếp quân vào hàng ngan dưới cùng, thứ tự từ 1 đến 9. Từ trái sang phải, quân số 0 xếp vào ô thứ 5 ở hàng ngang thứ 2 (có dấu chéo) phía trên ô số 5.

· Hai bên tự thỏa thuận (hoặc bốc thăm) để phân định vị trí ngồi chơi và người đi quân trước một nước, rồi lần lượt cho đến khi kết thúc cuộc chơi…(H3)

HÌNH 3 – CÁCH XẾP QUÂN

Cách đi quân

Quân số 0 không được di chuyển. Những quân còn lại đều được đi thẳng theo 4 hướng tiến, lùi, phải, trái và 4 phương chéo Đông, Tây, Nam, Bắc. Mỗi ô trống trên bàn cờ là một nước đi. Số bước đi được thực hiện theo trị số riêng của từng quân cờ. Những quân có trị số nhiều có thể thực hiện những bước đi ít hơn ( Ví dụ: Quân số 2 có thể đi từ 1 đến 2 ô.. quân số 9 có thể đi từ 1 đến 9 ô). Mỗi ô trống trên bàn cờ là một bước đi, không được vượt qua bất kỳ quân cờ nào cản đường…(H4)

H4 – HƯỚNG ĐI CỦA MỌI QUÂN CỜ

Cách bắt quân

- Muốn bắt quân đối phương phải có 2 quân bên mình đứng trong 2 ô liền kề nhau để lấy giá trị số của 2 quân cờ ấy tính nhẩm cộng, trừ, nhân, chia (+, _, x, ÷) với nhau. Đáp số của mỗi phép tính ấy là điểm được bắt quân đối phương.

* Chỉ đánh số nguyên đơn từ 1 đến 9 (quá 10, 20, 30…thì trừ đi 10, 20, 30…)

* Tính chia được đánh cả số dư.

* Hai số bất kỳ liền kề nhau sẽ có nhiều đáp số khi tính cộng, trừ, nhân, chia (+, _, x, ÷) với nhau nhưng khi bắt quân đối phương thì tự chọn lấy một đáp số:

- Thí dụ: 5 + 3 = 8

5 – 3 = 2

5 x 3 = 15(- 10) = 5

5 ÷ 3 = 1 dư 2

- Như vậy các đáp số 8, 2,5,1,2 là ô cờ có quân đối phương bị bắt. Hướng bắt quân đối phương cũng thực hiện như hướng đi quân ( 4 hướng tiến, lùi, phải, trái và 4 phương chéo Đông, Bắc, Tây, Nam).

- Khi bắt quân thì lấy quân đứng sau đặt vào vị trí quân đối phương bị bắt.(H5)

H5 – CÁCH BẮT QUÂN CỜ

* Bắt quân về hướng tay trái: * Bắt quân về hướng tay phải:

2 – 1 =1 1 x 2 = 2

2 x 1 = 2 1 + 2 = 3

2 + 1 = 3

D Kết thúc 1 ván cờ

Thắng tuyệt đối:

Bên nào bắt được quân cờ số O trước là thắng tuyệt đối.

Thắng điểm:

Mỗi dấu chấm tròn trên mặt quân cờ tương ứng với 1 điểm ( quân 1 chấm = 1 điểm, quân 2 = 2 điểm…)

- Hai bên tự thỏa thuân thang điểm cho mỗi ván đấu là 10, 15, 20 điểm. Bên nào đát số điểm đã thỏa thuận trước là thắng điểm.

- Trong trường hợp thi đấu để tranh giải thì phải tuân thủ moi qui định của Ban tổ chức giải.

sưu tầm tại nguồn

Feb 18, 2010

Tìm hiểu Objective - C phần 3

tiếp theo phần 2

Kiểu id
id trong ObC gần tương tự như void* trong C. bạn không cần phải biết rõ kiểu của object khi bạn gọi phương thức trong ObC điều này hoàn toàn khác với C++ bơi đơn giản khi gọi phương thức cũng giống như bạn truyền thông điệp trong ObC. Nếu đối tượng nó có phương thức thì sẽ đáp lại thông điệp mà bạn truyền (gọi phương thức) và phương thức đc gọi. Cũng nguy hiểm đây chứ .. :(


Ép kiểu động.
những phương thức dưới đây dùng để kiểm tra kiểu.

- (BOOL) isKindOfClass: classObj >> đối tượng là hậu duệ hoặc thể hiện của classObj
- (BOOL) isMemberOfClass: classObj >> là một thành phần của objClass
- (BOOL) respondsToSelector: selector >> đối tượng có phương thức bởi selector
+ (BOOL) instancesRespondToSelector: selector >> đối tượng đc tạo bởi lớp có đáp ứng selector
- (id) performSelector: selector >> triệu gọi chính sách selector trên đối tượng.


Constructors - hàm khỏi tạo:
Vấn đề là với một lớp thì hàm khởi tạo dùng để sinh đối tượng và cũng là chỗ để tư duy về hàm hủy và cách thức lưu trong bộ nhớ của đối tượng. Về vấn đề hủy đối tượng ta sẽ có một phần riêng và nó hoàn toàn khác biệt với việc viết hàm hủy trong C++ và các ngôn ngữ khác. Tất nhiên không có gì là không thể viết khi bạn đã hiểu rõ và thông thạo ngôn ngữ. Và hẳn nhiên bạn có thể quên hết những luật về khởi tạo đối tượng hàm tạo và hàm hủy của C++ vơi ObC bạn hoàn toàn có thể tự mình chế biến những hàm đó theo ý thích và cũng không có quy luật gì về tên tuổi của hàm, tuy nhiên theo thoi quen truyền thông để giúp style - code chở nên sáng sủa nên dùng bằng các từ như init hoặc tương tự... để định nghĩa hàm khởi tạo


Fraction.h
...
-(Fraction*) initWithNumerator: (int) n denominator: (int) d;
...



Fraction.m
...
-(Fraction*) initWithNumerator: (int) n denominator: (int) d {
self = [super init];

if ( self ) {
[self setNumerator: n andDenominator: d];
}

return self;
}
...



main.m
#import
#import "Fraction.h"

int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc] init];
Fraction *frac2 = [[Fraction alloc] init];
Fraction *frac3 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];

// set the values
[frac setNumerator: 1];
[frac setDenominator: 3];

// combined set
[frac2 setNumerator: 1 andDenominator: 5];

// print it
printf( "The fraction is: " );
[frac print];
printf( "\n" );

printf( "Fraction 2 is: " );
[frac2 print];
printf( "\n" );

printf( "Fraction 3 is: " );
[frac3 print];
printf( "\n" );

// free memory
[frac release];
[frac2 release];
[frac3 release];

return 0;
}

- Từ khóa supper để tham chiếu tới lớp cha.
- Từ khóa self tác dụng tương đương như this trong C++. (chính bản thân đang thể hiện của lớp - object hiện tại)
- Kết thúc hàm khởi tạo (init) sẽ trả về chính đối tượng dc tạo ra thông qua từ khóa self.
- Mặc định trong ObC hàm khỏi tạo là - (id) init;
- Trong ObC hàm khởi tạo chỉ có ý nghĩa về mặt tư duy, nó không đc đối sử đặc biết giống như C++.


Đa hình.
có lẽ với những trình bày ở trên phần nào giúp bạn mường tượng ra dc cơ chế đa hình của ObC. phần này chỉ là viết thêm nhằm củng cố một số những điểm sau đây.
1. Trong ObC không có từ khóa virtual và thực sự là không cần thiết vì nó sẽ không tạo ra những thứ quá phức tạp giống như C++ vì việc phủ quyết hàm trong ObC là phủ quyết trắng chợn không liên quan gì tới sự kế thừa. nếu 2 hàm giống hệt nhau ở 2 lớp quan hệ cha con thì cũng chẳng sao cả. cũng cần nói thêm là ObC là đơn kế thừa.
2. Quá trình tạo mối liên hệ giữa thể hiện của ObC và phương thức sẽ đc gọi là thời điểm run-time. Điểu này hoàn toàn có ý nghĩa nếu bạn gọi một phương thức mà bản thân đối tượng không có cũng không có lỗi gì. Lỗi chỉ xảy ra khi lời gọi đó dc thực hiện. Tuy nhiên ban cũng dc cung cấp những cơ chế để kiểm soát việc này. đây cũng là một đặc tính Run-Time của ObC nếu bạn quan tâm có thể tìm kiếm thông tin từ việc chuyển tiếp thông điệp (forward) tới một đối tượng khác.


Quản ly bộ nhớ.
ObC có 2 lựa chọn cho việc quản lý bộ nhớ. Thông thường bộ nhớ dc quản lý bởi lập trình viên, ObC có trình biên dịch chỉ thị nhứ "release", "retain", "autorelease" là những chỉ thị hỗ chợ lập trình viên mạnh mẽ trong việc quản lý bộ nhớ.
ObC sử dụng một tham chiếu đếm để dò tìm ra những thay đổi trên một đối tượng. Biến đếm này sẽ tăng lên một khi đối tượng dc cấp phát bộ nhớ bằng phương thức alloc, biến đếm này sẽ giảm đi một khi đối tượng dc giải phóng bằng phương thức dealloc. Như vậy nguyên lý cấp phát và duy trì bộ nhớ của đối tượng trong ObC dc sử dụng thông qua phương thức alloc và dealloc.

Mặt khác tiện ích khác từ kiểu dữ liệu nil đã nói ở trên đó việc giải phóng bộ nhơ. Trong ngữ cảnh một đối tượng của bạn là bao gồm nhiều những đối tượng khác. những đối tượng khác đó có thể đã dc giải phóng hoặc chưa. như thế bạn sẽ thực hiện lời gọi dealloc trên tập đối tượng mà bạn có, nếu con thì nó sẽ thực hiện giải phóng trong trường hợp bằng nil cũng ok :D không vấn đề gì (no error) vì nil cũng có thể truyền thông điệp.
hãy xem ví dụ

# AddressCard.h

#import
#import

@interface AddressCard: NSObject {
NSString *first;
NSString *last;
NSString *email;
}

-(AddressCard*) initWithFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e;
-(NSString*) first;
-(NSString*) last;
-(NSString*) email;
-(void) setFirst: (NSString*) f;
-(void) setLast: (NSString*) l;
-(void) setEmail: (NSString*) e;
-(void) setFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e;
-(void) setFirst: (NSString*) f last: (NSString*) l;
-(void) print;
@end

# AddressCard.m

#import "AddressCard.h"
#import

@implementation AddressCard
-(AddressCard*) initWithFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e {
self = [super init];

if ( self ) {
[self setFirst: f last: l email: e];
}

return self;
}

-(NSString*) first {
return first;
}

-(NSString*) last {
return last;
}

-(NSString*) email {
return email;
}

-(void) setFirst: (NSString*) f {
[f retain];
[first release];
first = f;
}

-(void) setLast: (NSString*) l {
[l retain];
[last release];
last = l;
}

-(void) setEmail: (NSString*) e {
[e retain];
[email release];
email = e;
}

-(void) setFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e {
[self setFirst: f];
[self setLast: l];
[self setEmail: e];
}

-(void) setFirst: (NSString*) f last: (NSString*) l {
[self setFirst: f];
[self setLast: l];
}

-(void) print {
printf( "%s %s <%s>", [first cString],
[last cString],
[email cString] );
}

-(void) dealloc {
[first release];
[last release];
[email release];

[super dealloc];
}
@end

# main.m

#import "AddressCard.h"
#import
#import

int main( int argc, const char *argv[] ) {
NSString *first =[[NSString alloc] initWithCString: "Tom"];
NSString *last = [[NSString alloc] initWithCString: "Jones"];
NSString *email = [[NSString alloc] initWithCString: "tom@jones.com"];
AddressCard *tom = [[AddressCard alloc] initWithFirst: first
last: last
email: email];

// we're done with the strings, so we must dealloc them
[first release];
[last release];
[email release];

// print to show the retain count
printf( "Retain count: %i\n", [[tom first] retainCount] );
[tom print];
printf( "\n" );
// free memory
[tom release];

return 0;
}

# output

Retain count: 1
Tom Jones

Mặt khác ObC cũng cung cấp một cớ chế thông minh thường thường trong việc bạn gọi và sử dụng đối tượng mà không phải quan tâm lo lắng đến việc cấp phát và giải phóng bộ nhớ đó là cơ chế NSAutoreleasePool. Để dùng dc cơ chế này bạn chỉ việc nhớ 2 điều kẹp đoạn code mà bạn muốn kiểm soát vào trong giữa NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] và [pool release]. Nguyên lý của đồng chí này cũng giống như lời gọi hàm vì thế bạn hoàn toàn có thể sử dụng lồng nhau và sự đóng mở hợp lý (giống như thẻ đóng và mở của XML đó) tự nhiên ObC sẽ đẩy các lời gọi pool sau xuống stack và đặt pool mới trên cùng sau đó nhét các object dc tạo ra trong lòng nó vào cái pool vừa mới tạo nếu song thì giải phóng rồi lại đẩy tiếp thằng pool ở dưới lên cứ thế... kinh chưa :).



Tổng kết:

Đây không phải là một ngôn ngữ compile và là ngôn ngữ run-time. Cho nên trong quá trình code yêu tố này ảnh hưởng rất lớn tới chương trình của bạn. Các đặc điểm như ép kiểu. Đa hình... sẽ rất mềm dẻo.


nội dung bài viết và vi dụ tham khảo tại:


các phần trước.


../..
 
Bạn có thể dùng bài viết của tôi tùy ý bạn nhưng vui lòng ghi lại rõ nguồn cung cấp
The world in a click_
Copyright © 2008 linhdkl