Tài liệu Ngôn ngữ lập trình C#: Phần 1 trình bày các nội dung: Microsoft.NET, ngôn ngữ C#, nền tảng ngôn ngữ C#, xây dựng lớp - đối tượng, kế thừa, đa hình, nạp chồng toán tử, cấu trúc. Đây là một Tài liệu hữu ích dành cho các bạn sinh viên đang theo học ngành Công nghệ thông tin tham khảo làm tư liệu học tập và nghiên cứu. Mời các bạn cùng tham khảo nội dung chi tiết.
NGƠN NGỮ LẬP TRÌNH C# Ngơn Ngữ Lập Trình C# Mục Lục Microsoft NET 10 Tình hình trước MS.NET đời 10 Nguồn gốc NET 12 Microsoft NET 12 Tổng quan 12 Kiến trúc NET Framework 13 Common Language Runtime 15 Thư viện NET Framework 16 Phát triển ứng dụng client 16 Biên dịch MSIL 17 Ngôn ngữ C# 18 Ngôn ngữ C# 20 Tại phải sử dụng ngôn ngữ C# 20 C# ngôn ngữ đơn giản 20 C# ngôn ngữ đại 21 C# ngôn ngữ hướng đối tượng 21 C# ngôn ngữ mạnh mẽ 22 C# ngơn ngữ từ khóa .22 C# ngôn ngữ module hóa 22 C# ngôn ngữ phổ biến 22 Ngôn ngữ C# với ngôn ngữ khác 23 Các bước chuẩn bị cho chương trình 24 Chương trình C# đơn giản 25 Phát triển chương trình minh họa 31 Câu hỏi & tập 35 Nền tảng ngôn ngữ C# 39 Kiểu liệu 40 Kiểu liệu xây dựng sẵn 41 Chọn kiểu liệu 42 Chuyển đổi kiểu liệu 43 Biến 44 Gán giá trị xác định cho biến 45 Hằng .46 Kiểu liệt kê .47 Ngơn Ngữ Lập Trình C# Kiểu chuỗi ký tự .50 Định danh .50 Biểu thức 50 Khoảng trắng 51 Câu lệnh 51 Phân nhánh khơng có điều kiện 52 Phân nhánh có điều kiện 53 Câu lệnh lặp 60 Toán tử 68 Namespace 76 Các dẫn biên dịch 80 Câu hỏi & tập 82 Xây dựng lớp - Đối tượng 87 Định nghĩa lớp 88 Thuộc tính truy cập 91 Tham số phương thức 92 Tạo đối tượng 93 Bộ khởi dựng 93 Khởi tạo biến thành viên 96 Bộ khởi dựng chép 98 Từ khóa this 99 Sử dụng thành viên static 100 Gọi phương thức static 101 Sử dụng khởi dựng static 101 Sử dụng khởi dựng private 102 Sử dụng thuộc tính static 102 Hủy đối tượng 104 Truyền tham số .107 Nạp chồng phương thức 112 Đóng gói liệu với thuộc tính 116 Thuộc tính đọc 119 Câu hỏi & tập 121 Kế thừa – Đa hình 125 Đặc biệt hóa tổng quát hóa 126 Sự kế thừa 129 Thực thi kế thừa 129 Gọi phương thức khởi dựng lớp sở .131 Gọi phương thức lớp sở 132 Ngơn Ngữ Lập Trình C# Điều khiển truy xuất .132 Đa hình 133 Kiểu đa hình 133 Phương thức đa hình 133 Từ khóa new override 137 Lớp trừu tượng 139 Gốc tất lớp- lớp Object 142 Boxing Unboxing liệu 144 Boxing liệu ngầm định 144 Unboxing phải thực tường minh 145 Các lớp lồng 147 Câu hỏi & tập 149 Nạp chồng toán tử 153 Sử dụng từ khóa operator .153 Hỗ trợ ngôn ngữ NET khác 154 Sử dụng toán tử 154 Toán tử so sánh 156 Toán tử chuyển đổi 157 Câu hỏi & tập 163 Cấu trúc 165 Định nghĩa cấu trúc 165 Tạo cấu trúc 168 Cấu trúc kiểu giá trị 168 Gọi khởi dựng mặc định 169 Tạo cấu trúc không gọi new 170 Câu hỏi & tập 172 Thực thi giao diện 176 Thực thi giao diện 177 Thực thi nhiều giao diện 180 Mở rộng giao diện 181 Kết hợp giao diện .181 Truy cập phương thức giao diện 187 Gán đối tượng cho giao diện 187 Toán tử is 188 Toán tử as .190 Giao diện đối lập với trừu tượng 192 Thực thi phủ giao diện 193 Thực thi giao diện tường minh .197 Ngơn Ngữ Lập Trình C# Lựa chọn thể phương thức giao diện 200 Ẩn thành viên 200 Câu hỏi & tập 207 Mảng, mục, tập hợp 211 Mảng 212 Khai báo mảng 213 Giá trị mặc định 214 Truy cập thành phần mảng 214 Khởi tạo thành phần mảng 216 Sử dụng từ khóa params 216 Câu lệnh foreach 218 Mảng đa chiều 220 Mảng đa chiều kích thước 220 Mảng đa chiều có kích thước khác 224 Chuyển đổi mảng 227 Bộ mục 232 Bộ mục phép gán 236 Sử dụng kiểu số khác 237 Giao diện tập hợp 241 Giao diện IEnumerable 242 Giao diện ICollection .246 Danh sách mảng 247 Thực thi IComparable 251 Thực thi IComparer 254 Hàng đợi 259 Ngăn xếp 262 Kiểu từ điển 265 Hastables 266 Giao diện IDictionary .267 Tập khóa tập giá trị 269 Giao diện IDictionaryEnumerator 270 Câu hỏi & tập 271 10 Xử lý chuỗi 275 Lớp đối tượng string 276 Tạo chuỗi 276 Tạo chuỗi dùng phương thức ToString 277 Thao tác chuỗi 278 Tìm chuỗi 285 Ngơn Ngữ Lập Trình C# Chia chuỗi 286 Thao tác chuỗi dùng StringBuilder 288 Các biểu thức quy tắc .290 Sử dụng biểu thức quy tắc qua lớp Regex 291 Sử dụng Regex để tìm tập hợp .294 Sử dụng Regex để gom nhóm 295 Sử dụng CaptureCollection 298 Câu hỏi & tập 301 11 Cơ chế ủy quyền kiện 303 Ủy quyền 304 Sử dụng ủy quyền xác nhận phương thức lúc thực thi 304 Ủy quyền tĩnh 314 Dùng ủy quyền thuộc tính .315 Thiết lập thứ tự thi hành với mảng ủy quyền 316 Multicasting 320 Sự kiện 324 Cơ chế publishing- subscribing 324 Sự kiện ủy quyền 325 Câu hỏi & tập 333 12 Các lớp sở NET 335 Lớp đối tượng NET Framework 335 Lớp Timer 337 Lớp thư mục hệ thống 340 Lớp Math 342 Lớp thao tác tập tin 345 Làm việc với tập tin liệu 351 Câu hỏi & tập 362 13 Xử lý ngoại lệ .364 Phát sinh bắt giữ ngoại lệ 365 Câu lệnh throw .365 Câu lệnh catch 367 Câu lệnh finally 373 Những đối tượng ngoại lệ 375 Tạo riêng ngoại lệ 378 Phát sinh lại ngoại lệ 381 Câu hỏi & tập 385 Ngơn Ngữ Lập Trình C# Tham Khảo Giáo trình “Ngơn ngữ Lập trình C#” biên dịch tổng hợp từ: Programming C#, Jesse Liberty, O’Reilly C# in 21 Days, Bradley L.Jones, SAMS Windows Forms Programming with C#, Erik Brown, Manning MSDN Library – April 2002 Quy ước Giáo trình sử dụng số quy ước sau: Các thuật ngữ giới thiệu lần in nghiêng Mã nguồn chương trình minh họa dùng font Verdana -10 Các từ khóa C# dùng font Verdana-10, đậm Verdana-10, bình thường Tên namspace, lớp, đối tượng, phương thức, thuộc tính, kiện dùng font Verdana10 Kết chương trình xuất hình console dùng font Courier New-10 Ngơn Ngữ Lập Trình C# Chương MICROSOFT NET Tình hình trước MS.NET đời Nguồn gốc NET Microsoft NET Tổng quan Kiến trúc NET Framework Common Language Runtime (CLR) Thư viện NET Framework Phát triển ứng dụng client Biên dịch MSIL Ngơn ngữ C# Tình hình trước MS.NET đời Trong lĩnh vực công nghệ thông tin giới ngày nay, với phát triển liên tục đa dạng phần mềm, hệ điều hành, môi trường phát triển, ứng dụng liên tục đời Tuy nhiên, việc phát triển không đồng lợi ích khác công ty phần mềm lớn làm ảnh hưởng đến người xây dựng phần mềm Cách vài năm Java Sun viết ra, có sức mạnh đáng kể, hướng tới việc chạy nhiều hệ điều hành khác nhau, độc lập với xử lý (Intel, Risc,…) Đặc biệt Java thích hợp cho việc viết ứng dụng Internet Tuy nhiên, Java lại có hạn chế mặt tốc độ thực tế chưa thịnh hành Mặc dù Sun Corporation IBM có đẩy mạnh Java, Microsoft dùng ASP để làm giảm khả ảnh hưởng Java Để lập trình Web, lâu người ta dùng CGI-Perl gần PHP, ngôn ngữ giống Perl tốc độ chạy nhanh Ta triển khai Perl Unix/Linux hay MS Windows Tuy nhiên có nhiều người khơng thích dùng thân ngôn ngữ hay qui ước khác thường Perl không phát triển thống nhất, công cụ xây dựng cho Perl mạnh nhiều nhóm phát triển người ta khơng đảm bảo tương lai ngày tốt đẹp Microsoft NET Ngơn Ngữ Lập Trình C# Trong giới phát triển ứng dụng Windows ta viết ứng dụng Visual C++, Delphi hay Visual Basic, số công cụ phổ biến mạnh Trong Visual C++ ngơn ngữ mạnh khó sử dụng Visual Basic đơn giản dễ học, dễ dùng nên thông dụng Lý Visual Basic giúp viết chương trình Windows dễ dàng mà khơng cần thiết phải biết nhiều cách thức MS Windows hoạt động, ta cần biết số kiến thức tối thiểu MS Windows lập trình Do theo quan điểm Visual Basic nên liên kết với Windows điều tự nhiên dễ hiểu, hạn chế Visual Basic ngôn ngữ hướng đối tượng (Object Oriented) Delphi hậu duệ Turbo Pascal Borland Nó giống tương đối dễ dùng Visual Basic Delphi ngôn ngữ hướng đối tượng Các điều khiển dùng Form Delphi tự động khởi tạo mã nguồn Tuy nhiên, chức khởi động mã nguồn Delphi đơi gặp rắc rối có can thiệp người dùng vào Sau công ty Borland bị bán chuyên gia xây dựng nên Delphi chạy qua bên Microsoft, Delphi khơng cịn phát triển tốt nữa, người ta khơng dám đầu tư triển khai phần mềm vào Delphi Công ty sau phát triển dòng sản phẩm Jbuilder (dùng Java) khơng cịn quan tâm đến Delphi Tuy Visual Basic bền không cần phải khởi tạo mã nguồn Form thiết kế Visual Basic có nhiều khuyết điểm : Khơng hỗ trợ thiết kế hướng đối tượng, khả thừa kế (inheritance) Giới hạn việc chạy nhiều tiểu trình ứng dụng, ví dụ ta khơng thể dùng Visual Basic để viết Service kiểu NT Khả xử lý lỗi yếu, khơng thích hợp mơi trường Multi- tier Khó dùng chung với ngơn ngữ khác C++ Khơng có User Interface thích hợp cho Internet Do Visual Basic khơng thích hợp cho viết ứng Web Server nên Microsoft tạo ASP (Active Server Page) Các trang ASP vừa có tag HTML vừa chứa đoạn script (VBScript, JavaScript) nằm lẫn lộn Khi xử lý trang ASP, tag HTML gởi thẳng qua Browser, cịn script chuyển thành dịng HTML gởi đi, ngoại trừ function hay sub ASP vị trí script khác quan trọng Khi số chức viết tốt người ta dịch thành ActiveX đưa vào Web Server Tuy nhiên lý bảo mật nên ISP (Internet Service Provider) làm máy chủ cho Web site thường dè đặt cài ActiveX lạ máy họ Ngoài việc tháo gỡ phiên ActiveX cơng việc khó, thường xun làm cho Administrator nhức đầu Những người quản lý version DLL Windows điều than phiền phải đăng ký DLL đăng ký phiên DLL mà Và từ “DLL Hell” xuất tức địa ngục DLL… Microsoft NET Ngơn Ngữ Lập Trình C# Sau để giúp cho việc lập trình ASP nhanh cơng cụ Visual InterDev, IDE (Integrated Development Environment) đời Visual InterDev tạo Design Time Controls cho việc thiết kế điều khiển web,… Tiếc thay Visual InterDev không bền vững nên sau thời gian nhà phát triển rời bỏ Tóm lại thân ASP số khuyết điểm quan trọng, chạy Internet Information Server với Windows NT 4, ASP khơng đáng tin cậy Tóm lại giới lập trình theo Microsoft việc lập trình desktop lập trình hệ phân tán hay web không nhịp nhàng cho Để chuyển từ lập trình client hay desktop đến lập trình web chặng đường dài Nguồn gốc NET Đầu năm 1998, sau hoàn tất phiên Version Internet Information Server (IIS), đội ngũ lập trình Microsoft nhận thấy họ nhiều sáng kiến để kiện toàn IIS Họ bắt đầu xây dựng kiến trúc tảng ý tưởng đặt tên Next Generation Windows Services (NGWS) Sau Visual Basic trình làng vào cuối 1998, dự án mang tên Visual Studio xác nhập vào NGWS Đội ngũ COM+/MTS góp vào universal runtime cho tất ngơn ngữ lập trình chung Visual Studio, tham vọng họ cung cấp cho ngôn ngữ lập trình cơng ty khác dùng chung ln Cơng việc xúc tiến cách hồn tồn bí mật hội nghị Professional Developers’ Conference Orlado vào tháng 7/2000 Đến tháng 11/2000 Microsoft phát hành Beta NET gồm đĩa CD Tính đến lúc Microsoft làm việc với NET gần năm rồi, Beta tương đối vững .NET mang dáng dấp sáng kiến áp dụng trước p-code UCSD Pascal Java Virtual Machine Có điều Microsoft góp nhặt sáng kiến người khác, kết hợp với sáng kiến để làm nên sản phẩm hồn chỉnh từ bên lẫn bên ngồi Hiện Microsoft cơng bố phiên release NET Thật Microsoft đặt cược vào NET theo thơng tin cơng ty, tập trung 80% sức mạnh Microsoft để nghiên cứu triển khai NET (bao gồm nhân lực tài ?), tất sản phẩm Microsoft chuyển qua NET Microsoft NET Tổng quan Microsoft NET gồm phần : Framework Integrated Development Environment (IDE) Framework cung cấp cần thiết bản, chữ Framework có nghĩa khung hay khung cảnh ta dùng hạ tầng sở theo qui ước định để công việc trơi chảy IDE cung cấp mơi trường giúp triển khai dễ dàng, nhanh chóng ứng dụng dựa tảng NET Nếu IDE 10 Microsoft NET Ngơn Ngữ Lập Trình C# } Sự chuyển đổi thực cách ngầm định số nguyên chuyển thành phân số cách thiết lập tử số giá trị số nguyên mẫu số có giá trị Việc thực giao lại cho phương thức khởi dựng lấy tham số Toán tử chuyển đổi thứ hai thực cách tường minh, chuyển từ Fraction số nguyên: public static explicit operator int( Fraction theFraction ) { return theFraction.numerator / theFraction.denominator; } Bởi ví dụ sử dụng phép chia nguyên, phép chia cắt bỏ phần phân lấy phần nguyên Do phân số có giá trị 16/15 kết số nguyên trả Một số phép chuyển đổi tốt cách sử dụng làm tròn số Tiếp theo sau toán tử so sánh (==) tốn tử so sánh khơng (!=) Chúng ta nên nhớ thực thi toán tử so sánh phải thực thi tốn tử so sánh không Chúng ta định nghĩa giá trị hai Fraction tử số tử số mẫu số mẫu số Vi dụ, hai phân số 3/4 6/8 khơng so sánh Một lần nữa, thực thi tốt tối giản tử số mẫu số 6/8 đơn giản thành 3/4 so sánh hai phân số Trong lớp thực thi phủ phương thức Equals() lớp object, đối tượng Fraction đối xử cách đa hình với đối tượng khác Trong phần thực thi phương thức ủy thác việc so sánh lại cho toán tử so sánh cách gọi tốn tử (==) Lớp Fraction thực thi hết tất toán tử số học cộng, trừ, nhân, chia Tuy nhiên, phạm vi nhỏ hẹp minh họa thực thi toán tử cộng, chí phép cộng thực đơn giản Chúng ta thử nhìn lại, hai mẫu số ta cộng tử số: public static Fraction operator + ( Fraction lhs, Fraction rhs) { if ( lhs.denominator == rhs.denominator) { return new Fraction( lhs.numerator + rhs.numerator, lhs.denominator); } } Nếu mẫu số khơng nhau, thực nhân chéo: int firstProduct = lhs.numerator * rhs.denominator; int secondProduct = rhs.numerator * lhs.denominator; return new Fraction( firstProduct + secondProduct, lhs.denominator * 161 Nạp Chồng Tốn Tử Ngơn Ngữ Lập Trình C# rhs.denominator); Cuối phủ phương thức ToString() lớp object, phương thức thực viết xuất nội dung phân số dạng : tử số / mẫu số: public override string ToString() { string s = numerator.ToString() + “/” + denominator.ToString(); return s; } Chúng ta tạo chuỗi cách gọi phương thức ToString() numerator Do numerator đối tượng, nên trình biên dịch ngầm định thực boxing số nguyên numerator sau gọi phương thức ToString(), trả chuỗi thể giá trị số nguyên numerator Sau ta nối chuỗi với “/” cuối chuỗi thể giá trị mẫu số Với lớp Fraction tạo ra, thực kiểm tra lớp Đầu tiên tạo hai phân số 3/4, 2/4: Fraction f1 = new Fraction( 3, 4); Console.WriteLine("f1:{0}",f1.ToString()); Fraction f2 = new Fraction( 2, 4); Console.WriteLine("f2:{0}",f2.ToString()); Kết thực lệnh sau: In Fraction Constructor(int, int) f1: 3/4 In Fraction Constructor(int, int) f2: 2/4 Do phương phức khởi dựng lớp Fraction có gọi hàm WriteLine() để xuất thông tin khởi dựng nên tạo đối tượng (new) thơng tin hịển thị Dòng hàm Main() gọi toán tử cộng, phương thức tĩnh Mục đích tốn tử cộng hai phân số trả phân số tổng hai phân số đưa vào: Fraction f3 = f1 + f2; Console.WriteLine(“f1 + f2 = f3: {0}”, f3.ToString()); Hai câu lệnh cho kết sau: In operator + In Fraction Constructor( int, int) f1 + f2 = f3: 5/4 Toán tử + gọi trước sau đến phương thức khởi dựng đối tượng f3 Phương thức khởi dựng lấy hai tham số nguyên để tạo tử số mẫu số phân số f3 162 Nạp Chồng Tốn Tử Ngơn Ngữ Lập Trình C# Hai câu lệnh cộng giá trị nguyên vào phân số f3 gán kết cho phân số f4: Fraction f4 = f3 + 5; Console.WriteLine(“f3 + = f4: {0}”, f4.ToString()); Kết trình bày theo thứ tự sau: In implicit conversion to Fraction In Fraction Construction(int) In operator+ In Fraction Constructor(int, int) f3 + = f4: 25/4 Ghi chú: toán tử chuyển đổi ngầm định gọi chuyển thành phân số Phân số tạo từ toán tử chuyển đổi ngầm định gọi phương thức khởi dựng tham số để tạo phân số 5/1 Phân số chuyển thành toán hạng phép cộng với phân số f3 kết trả phân số f4 tổng hai phân số Thử nghiệm cuối tạo phân số f5, sau gọi tốn tử nạp chồng so sánh để kiểm tra xem hai phân số có hay không Câu hỏi trả lời Câu hỏi 1: Có phải xây dựng lớp cần dùng nạp chồng toán tử với chức tính tốn ? Trả lời 1: Đúng vậy, việc thực nạp chồng toán tử tự nhiên trực quan Tuy nhiên số ngôn ngữ NET VB.NET khơng hỗ trợ việc nạp chồng tốn tử nên, tốt muốn cho lớp C# gọi từ ngơn ngữ khác khơng hỗ trợ nạp chồng tốn tử nên xây dựng phương thức tương đương để thực chức như: Add, Sub, Mul, Câu hỏi 2: Những điều lưu ý sử dụng nạp chồng toán tử lớp? Trả lời 2: Nói chung thật cần thiết gây nhầm lẫn Ví dụ ta xây dựng lớp Employee có nhiều thuộc tính số lương, thâm niên, tuổi Chúng ta muốn xây dựng toán tử ++ cho lương làm nhầm lẫn với việc tăng số năm công tác, hay tăng tuổi Do việc sử dụng nạp chồng toán tử phải cân nhắc tránh gây nhầm lẫn Tốt sử dụng lớp có thuộc tính số Câu hỏi 3: Khi xây dựng tốn tử so sánh có phải cần dùng toán tử so sánh bằng? Trả lời 3: Đúng cần dùng toán tử so sánh tạo tốn tử so sánh mà thơi Tuy nhiên, tốt nên xây dựng thêm toán tử so sánh khác như: so sánh khác, so sánh nhỏ hơn, so sánh lớn Việc làm cho lớp hoàn thiện Câu hỏi thêm 163 Nạp Chồng Tốn Tử Ngơn Ngữ Lập Trình C# Câu hỏi 1: Khi sử dụng tốn tử chuyển đổi? Thế chuyển đổi tường minh chuyển đổi ngầm định? Câu hỏi 2: Có thể tạo ký toán tử riêng ta thực thi nạp chồng tốn tử hay khơng? Câu hỏi 3: Có tốn tử mà NET quy định? Ký hiệu toán tử? Bài tập Bài tập 1: Hãy tiếp tục phát triển lớp Fraction ví dụ chương cách thêm tốn tử khác trừ, nhân, chia, so sánh Bài tập 2: Xây dựng lớp điểm không gian hai chiều, với toán tử cộng, trừ, nhân, chia Bài tập 3: Tương tự tập điểm nằm không gian chiều Bài tập 4: Xây dựng lớp số phúc (số ảo) với phép toán cộng, trừ, nhân, chia 164 Nạp Chồng Tốn Tử Ngơn Ngữ Lập Trình C# Chương CẤU TRÚC Định nghĩa cấu trúc Tạo cấu trúc Cấu trúc kiểu giá trị Gọi khởi dựng mặc định Tạo cấu trúc không gọi new Câu hỏi & tập Cấu trúc kiểu liệu đơn giản người dùng định nghĩa, kích thước nhỏ dùng để thay cho lớp Những cấu trúc tương tự lớp chứa phương thức, thuộc tính, trường, tốn tử, kiểu liệu lồng bên mục (indexer) Có số khác quan trọng lớp cấu trúc Ví dụ, cấu trúc khơng hỗ trợ kế thừa hủy giống kiểu lớp Một điều quan trọng lớp kiểu liệu tham chiếu, cấu trúc kiểu lịêu giá trị (Chương thảo luận kiểu liệu tham chiếu kiểu liệu giá trị) Do cấu trúc thường dùng để thể hiển đối tượng khơng địi hỏi ngữ nghĩa tham chiếu, hay lớp nhỏ mà đặt vào stack có lợi đặt nhớ heap Một nhận xét rút nên sử dụng cấu trúc với kiểu liệu nhỏ, hành vi hay thuộc tính giống kiểu liệu xây dựng sẵn Cấu trúc có hiệu sử dụng chúng mảng nhớ (Chương 9) Tuy nhiên, cấu trúc hiệu sử dụng dạng tập hợp (collections) Tập hợp xây dựng hướng tới kiểu liệu tham chiếu Trong chương tìm hiểu định nghĩa làm việc với kiểu cấu trúc cách sử dụng khởi dựng để khởi tạo giá trị cấu trúc Định nghĩa cấu trúc Cú pháp để khai báo cấu trúc tương tự cách khai báo lớp: [thuộc tính] [bổ sung truy cập] struct [: danh sách giao diện] { [thành viên cấu trúc] 165 Cấu Trúc Ngơn Ngữ Lập Trình C# } Ví dụ 7.1 sau minh họa cách tạo cấu trúc Kiểu Location thể điểm không gian hai chiều Lưu ý cấu trúc Location khai báo xác thực khai báo với lớp, ngoại trừ việc sử dụng từ khóa struct Ngồi lưu ý hàm khởi dựng Location lấy hai số nguyên gán giá trị chúng cho biến thành viên, x y Tọa độ x y Location khai báo thuộc tính Ví dụ 7.1 Tạo cấu trúc using System; public struct Location { public Location( int xCoordinate, int yCoordinate) { xVal = xCoordinate; yVal = yCoordinate; } public int x { get { return xVal; } set { xVal = value; } } public int y { get { return yVal; } set { yVal = value; } } 166 Cấu Trúc Ngơn Ngữ Lập Trình C# public override string ToString() { return (String.Format(“{0}, {1}”, xVal, yVal)); } // thuộc tính private lưu toạ độ x, y private int xVal; private int yVal; } public class Tester { public void myFunc( Location loc) { loc.x = 50; loc.y = 100; Console.WriteLine(“Loc1 location: {0}”, loc); } static void Main() { Location loc1 = new Location( 200, 300); Console.WriteLine(“Loc1 location: {0}”, loc1); Tester t = new Tester(); t.myFunc( loc1 ); Console.WriteLine(“Loc1 location: {0}”, loc1); } } Không giống lớp, cấu trúc không hỗ trợ việc thừa kế Chúng thừa kế ngầm định từ lớp object (tương tự tất kiểu liệu C#, bao gồm kiểu liệu xây dựng sẵn) kế thừa từ lớp khác hay cấu trúc khác Cấu trúc ngầm định sealed, điều có ý nghĩa khơng có lớp hay cấu trúc dẫn xuất từ Tuy nhiên, giống lớp, cấu trúc thực thi nhiều giao diện Sau số khác là: Khơng có hủy khởi tạo mặc định tùy chọn: Những cấu trúc khơng có hủy khơng có khởi tạo mặc định không tham số tùy chọn Nếu không cung cấp khởi tạo cấu trúc cung cấp khởi tạo mặc định, giá trị thiết lập cho tất liệu thành viên hay giá trị mặc định tương ứng cho kiểu liệu (bảng 4.2) Nếu cung cấp khởi dựng phải khởi tạo tất trường cấu trúc 167 Cấu Trúc Ngơn Ngữ Lập Trình C# Khơng cho phép khởi tạo: khởi tạo trường thể (instance fields) cấu trúc, đoạn mã nguồn sau khơng hợp lệ: private int xVal = 20; private int yVal = 50; điều thực tốt lớp Cấu trúc thiết kế hướng tới đơn giản gọn nhẹ Trong liệu thành viên private hỗ trợ việc che dấu liệu đóng gói Một vài người lập trình có cảm giác điều phá hỏng cấu trúc Họ tạo liệu thành viên public, đơn giản thực thi cấu trúc Những người lập trình khác có cảm giác thuộc tính cung cấp giao diện rõ ràng, đơn giản việc thực lập trình tốt địi hỏi phải che dấu liệu chí với liệu đơn giản Chúng ta chọn cách nào, nói chung phụ thuộc vào quan nệm thiết kế người lập trình Dù chọn cách ngơn ngữ C# hỗ trợ hai cách tiếp cận Tạo cấu trúc Chúng ta tạo thể cấu trúc cách sử dụng từ khóa new câu lệnh gán, tạo đối tượng lớp Như ví dụ 7.1, lớp Tester tạo thể Location sau: Location loc1 = new Location( 200, 300); Ở thể tên loc1 truyền hai giá trị 200 300 Cấu trúc kiểu giá trị Phần định nghĩa lớp Tester ví dụ 7.1 bao gồm đối tượng Location loc1 tạo với giá trị 200 300 Dòng lệnh sau gọi thực khởi tạo cấu trúc Location: Location loc1 = new Location( 200, 300); Sau phương tức WriteLine() gọi: Console.WriteLine(“Loc1 location: {0}”, loc1); Dĩ nhiên WriteLine chờ đợi đối tượng, Location cấu trúc (một kiểu giá trị) Trình biên dịch tự động boxing cấu trúc (cũng giống trình biên dịch làm với kiểu liệu giá trị khác) Một đối tượng sau boxing truyền vào cho phương thức WriteLine() Tiếp sau phương thức ToString() gọi đối tượng boxing này, cấu trúc ngầm định kế thừa từ lớp object, đáp ứng đa hình, cách phủ phương thức đối tượng khác Loc1 location 200, 300 Tuy nhiên cấu trúc kiểu giá trị, nên truyền vào hàm, chúng truyền giá trị vào hàm Cũng ta thấy dịng lệnh kế tiếp, đối tượng Location truyền vào phương thức myFunc(): t.myFunc( loc1 ); 168 Cấu Trúc Ngơn Ngữ Lập Trình C# Trong phương thức myFunc() hai giá trị gán cho x y, sau giá trị xuất hình: Loc1 location: 50, 100 Khi phương thức myFunc() trả cho hàm gọi ( Main()) gọi tiếp phương thức WriteLine() lần giá trị khơng thay đổi: Loc1 location: 200, 300 Như cấu trúc truyền vào hàm đối tượng giá trị, tạo bên phương thức myFunc() Nếu thử đổi khai báo Location class sau: public class Location Sau chạy lại chương trình có kết quả: Loc1 location: 200, 3000 In myFunc loc: 50, 100 Loc1 location: 50, 100 Lúc Location đối tượng tham chiếu nên truyền vào phương thức myFunc() việc gán giá trị cho x y điều làm thay đổi đối tượng Location Gọi khởi dựng mặc định Như đề cập phần trước, khơng tạo khởi dựng khởi dựng mặc định ngầm định trình biên dịch tạo Chúng ta nhìn thấy điều bỏ khởi dựng tạo ra: /*public Location( int xCoordinate , int yCoordinate) { xVal = xCoordinate; yVal = yCoordinate; } */ ta thay dòng lệnh hàm Main() tạo Location có hai tham số câu lệnh tạo không tham số sau: //Location loc1 = new Location( 200, 300) Location loc1 = new Location(); Bởi lúc khơng có phương thức khởi dựng khai báo, phương thức khởi dựng ngầm định gọi Kết thực giống sau: Loc1 location 0, In myFunc loc: 50, 100 Loc1 location: 0, Bộ khởi tạo mặc định thiết lập tất biến thành viên với giá trị 169 Cấu Trúc Ngôn Ngữ Lập Trình C# Ghi chú: Đối với lập trình viên C++ lưu ý, ngơn ngữ C#, từ khóa new khơng phải luôn tạo đối tượng nhớ heap Các lớp tạo heap, cấu trúc tạo stack Ngồi ra, new bỏ qua (sẽ bàn tiếp phần sau), khởi dựng khơng gọi Do ngơn ngữ C# u cầu phải có phép gán trước sử dụng, phải khởi tạo tường minh tất biến thành viên trước sử dụng chúng cấu trúc Tạo cấu trúc không gọi new Bởi Location cấu trúc khơng phải lớp, thể tạo stack Trong ví dụ 7.1 tốn tử new gọi: Location loc1 = new Location( 200, 300); kết đối tượng Location tạo stack Tuy nhiên, toán tử new gọi khởi dựng lớp Location, không giống với lớp, cấu trúc tạo mà khơng cần phải gọi toán tử new Điều giống biến kiểu liệu xây dựng sẵn (như int, long, char, ) tạo Ví dụ 7.2 sau minh họa việc tạo cấu trúc không sử dụng toán tử new Ghi chú: Đây khuyến cáo, ví dụ sau minh họa cách tạo cấu trúc mà khơng phải sử dụng tốn tử new có khác C# ngơn ngữ C++ khác cách ngôn ngữ C# đối xử với lớp khác cấu trúc Tuy nhiên, việc tạo cấu trúc mà khơng dùng từ khóa new khơng có lợi tạo chương trình khó hiểu, tiềm ẩn nhiều lỗi, khó trì Chương trình họa sau khơng khuyến khích Ví dụ 7.2: Tạo cấu trúc mà không sử dụng new using System; public struct Location { public Location( int xCoordinate, int yCoordinate) { xVal = xCoordinate; yVal = yCoordinate; } public int x { get { return xVal; } 170 Cấu Trúc Ngơn Ngữ Lập Trình C# set { xVal = value; } } public int y { get { return yVal; } set { yVal = value; } } public override string ToString() { return (string.Format(“{0} ,{1}”, xVal, yVal)); } // biến thành viên lưu tọa độ x, y public int xVal; public int yVal; } public class Tester { static void Main() { Location loc1; loc1.xVal = 100; loc1.yVal = 250; Console.WriteLine(“loc1”); } } Trong ví dụ 7.2 khởi tạo biến thành viên cách trực tiếp, trước gọi phương thức loc1 trước truyền đối tượng cho phương thức WriteLine(): loc1.xVal = 100; 171 Cấu Trúc Ngơn Ngữ Lập Trình C# loc2.yVal = 250; Nếu thử bỏ lệnh gán biên dịch lại: static void Main() { Location loc1; loc1.xVal = 100; //loc1.yVal = 250; Console.WriteLine( loc1 ); } Chúng ta nhận lỗi biên dịch sau: Use of unassigned local variable ‘loc1’ Một mà gán tất giá trị cấu trúc, truy cập giá trị thơng qua thuộc tính x thuộc tính y: static void Main() { Location loc1; // gán cho biến thành viên loc1.xVal = 100; loc1.yVal = 250; // sử dụng thuộc tính loc1.x = 300; loc1.y = 400; Console.WriteLine( loc1 ); } Hãy cẩn thận với việc sử dụng thuộc tính Mặc dù cấu trúc cho phép hỗ trợ đóng gói việc thiết lập thuộc tính private cho biến thành viên Tuy nhiên thân thuộc tính thật phương thức thành viên,và gọi phương thức thành viên khởi tạo tất biến thành viên Như ví dụ ta thiết lập thuộc tính truy cập hai biến thành viên xVal yVal public phải khởi tạo giá trị hai biến thành viên bên cấu trúc, trước thuộc tính sử dụng Câu hỏi trả lời Câu hỏi 1: Có khác cấu trúc lớp? Trả lời 1: Đúng có số khác cấu trúc lớp Như đề cập lý thuyết lớp kiểu liệu tham chiếu cấu trúc kiểu liệu giá trị Điều xem khác cấu trúc lớp Ngồi cấu trúc khơng cho phép có hàm hủy tạo khởi dựng không tham số tường minh Cấu trúc khác lớp cấu trúc 172 Cấu Trúc Ngơn Ngữ Lập Trình C# kiểu cô lập tường minh, tức không cho phép kế thừa từ Và khơng kế thừa từ lớp khác Mặc nhiên, cấu trúc kế thừa từ Object kiểu liệu giá trị khác C#/ Câu hỏi 2: Trong hai dạng mảng tập hợp lại chứa cấu trúc tốt hơn? Trả lời 2: Cấu trúc có hiệu sử dụng mảng lưu chúng dạng tập hợp Dạng tập hợp tốt với kiểu liệu tham chiếu Câu hỏi 3: Cấu trúc lưu trữ đâu? Trả lời 3: Cấu trúc đề cập kiểu liệu giá trị nên lưu trữ stack chương trình Ngược với kiểu tham chiếu đặt heap Câu hỏi 4: Khi truyền cấu trúc cho phương thức hình thức nào? Trả lời 4: Do kiểu giá trị nên truyền đối tượng cấu trúc cho phương thức truyền dạng tham trị tham chiếu Câu hỏi 5: Vậy làm truyền cấu trúc dạng tham chiếu cho phương thức? Trả lời 5: Cũng giống truyền tham chiếu kiểu giá trị int, long, char Ta khai báo khóa ref cho tham số kiểu cấu trúc Và gọi phương thức thêm từ khóa ref vào trước đối mục cấu trúc truyền vào Câu hỏi thêm Câu hỏi 1: Chúng ta khởi tạo giá trị ban đầu cho biến thành viên bên không? Nếu không sao? struct myStruct { private int mNum = 100; } Câu hỏi 2: Sự khác kiểu liệu tham chiếu kiểu liệu giá trị? Câu hỏi 3: Sự khác khởi dựng cấu trúc khởi dựng lớp? Câu hỏi 4: Có thiết phải dùng từ khóa new để tạo đối tượng kiểu cấu trúc hay khơng? Nếu khơng cịn cách khác nữa? Câu hỏi 5: Quá trình boxing unboxing có diễn với đối tượng kiểu cấu trúc hay không? Bài tập Bài tập 1: Chương trình sau có lỗi Hãy sửa lỗi, biên dịch, chạy chương trình Đoạn lệnh gây lỗi? using System; struct TheStruct { 173 Cấu Trúc Ngơn Ngữ Lập Trình C# public int x; public TheStruct() { x = 10; } } class TestClass { public static void structtaker( TheStruct s) { s.x = 5; } public static void Main() { TheStruct a = new TheStruct(); a.x = 1; structtaker( a); Console.WriteLine("a.x = {0}", a.x); } } Bài tập 2: Hãy tính kết tay mà chương trình sau xuất Sau biên dịch chạy chương trình để đối sánh kết using System; class TheClass { public int x; } struct TheStruct { public int x; } class TestClass { public static void structtaker( TheStruct s) { 174 Cấu Trúc Ngơn Ngữ Lập Trình C# s.x = 5; } public static void classtaker(TheClass c) { c.x = 5; } public static void Main() { TheStruct a = new TheStruct(); TheClass b = new TheClass(); a.x = 1; b.x = 1; structtaker( a); classtaker(b); Console.WriteLine("a.x = {0}", a.x); Console.WriteLine("b.x = {0}", b.x); } } Bài tập 3: Hãy sửa chương trình tập để kết giá trị a.x đối tượng a thay đổi khỏi hàm structtaker() Dùng truyền tham chiếu cho cấu trúc 175 Cấu Trúc ... C# ngôn ngữ đại C# ngôn ngữ hướng đối tượng C# ngôn ngữ mạnh mẽ mềm dẻo 18 Ngôn Ngữ C# Ngôn Ngữ Lập Trình C# C# ngơn ngữ có từ khóa C# ngơn ngữ hướng module C# trở nên phổ biến C# ngôn. .. giải phóng 17 Microsoft NET Ngơn Ngữ Lập Trình C# Chương NGƠN NGỮ C# Tại phải sử dụng ngôn ngữ C# C# ngôn ngữ đơn giản C# ngôn ngữ đại C# ngôn ngữ hướng đối tượng C# ngôn ngữ mạnh mẽ... có hiệu C# ngôn ngữ phổ biến 20 Ngôn Ngữ C# Ngơn Ngữ Lập Trình C# C# ngơn ngữ lập trình Vào thời điểm sách viết, khơng biết ngôn ngữ phổ biến Nhưng ngôn ngữ có số lý để trở thành ngơn ngữ phổ biến