Tập bài giảng Lập trình trên nền web (Phần 1)
Bạn đang xem 20 trang mẫu của tài liệu "Tập bài giảng Lập trình trên nền web (Phần 1)", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Tài liệu đính kèm:
- tap_bai_giang_lap_trinh_tren_nen_web_phan_1.pdf
Nội dung text: Tập bài giảng Lập trình trên nền web (Phần 1)
- MỤC LỤC LỜI NÓI ĐẦU 4 CHƢƠNG 1: TỔNG QUAN VỀ ASP.NET 5 1.1. Giới thiệu tổng quan về công nghệ .NET 5 1.1.1. Sự ra đời của .NET 5 1.1.2. .NET Framework 5 1.1.3. Ƣu điểm chính của .NET Framework 7 1.2. Giới thiệu về ASP.NET 8 1.3. Cài đặt Visual Studio.NET 8 1.3.1. Các phiên bản .NET 8 1.3.2. Cài đặt Visual Studio.NET 8 1.3.3. Giao diện Visual Studio.NET 9 1.4. Xây dựng ứng dụng Web 11 1.4.1. Tạo mới ứng dụng Web 11 1.4.2. Lƣu ứng dụng Web 12 1.4.3. Chạy ứng dụng Web 12 1.5. Bài tập 13 CHƢƠNG 2: NGÔN NGỮ LẬP TRÌNH C# 14 2.1. Giới thiệu về ngôn ngữ lập trình C# 14 2.2. Cấu trúc một chƣơng trình C# 15 2.3. Các kiểu dữ liệu 15 2.3.1. Kiểu dữ liệu xây dựng sẵn 16 2.3.2. Chọn kiểu dữ liệu 17 2.3.3. Chuyển đổi kiểu dữ liệu 18 2.3.4. Kiểu dữ liệu mảng 18 2.3.5. Kiểu dữ liệu xâu 20 2.4. Biến và hằng 20 2.5. Biểu thức và toán tử 21 2.6. Các lệnh điều khiển 22 2.6.1. Các câu lệnh rẽ nhánh 22 2.6.2. Các câu lệnh lặp 27 2.7. Xây dựng lớp và đối tƣợng 31 2.7.1. Xây dựng lớp 31 2.7.2. Tạo đối tƣợng 35 2.8. Xử lý ngoại lệ 36 2.8.1. Câu lệnh throw 37 2.8.2. Câu lệnh catch 38 2.8.3. Câu lệnh finally 43
- 2.9. Bài tập 45 CHƢƠNG 3: LÀM VIỆC VỚI WEB FORM 51 3.1. ASP.NET và Web Form 51 3.1.1. Mô hình lập trình phía máy chủ 51 3.1.2. Giới thiệu về ASP.NET 52 3.1.3. Cơ chế xử lý file ASP.NET phía máy chủ 54 3.1.4. Web Form trong ASP.NET 58 3.1.5. Tìm hiểu cấu trúc trang ASP.NET 58 3.1.6. Các phƣơng pháp viết mã trong ASP.NET 60 3.1.7. ASP.NET Server Control 62 3.1.7. Điều khiển Validation Controls 119 3.2. Tạo và sử dụng Custom Control 135 3.2.1. Giới thiệu User Custom Control 135 3.2.2. Các bƣớc tạo User Custom Control 135 3.2.3. Thêm các thuộc tính, phƣơng thức và sự kiện vào UCC 137 3.2.4. Truy cập thuộc tính, phƣơng thức của các phần tử con trong UCC 139 3.3. Các đối tƣợng cơ bản trong ASP.NET 143 3.3.1. Đối tƣợng Request 144 3.3.2. Đối tƣợng Response 147 3.3.3. Đối tƣợng Server 150 3.3.4. Đối tƣợng Session 151 3.3.5. Đối tƣợng Application 153 3.3.6. Đối tƣợng Cookies 155 3.4. Tệp tin quản lí và cấu hình ứng dụng 158 3.4.1. Tệp tin Global.asax 158 3.4.2. Tệp tin Web.config 160 3.5. Làm việc với giao diện Web 163 3.5.1. Master Page 163 3.5.2. Cascading Style Sheets - CSS 167 3.5.3. Theme và Skin 172 3.5.4. Navigation Controls 176 3.6. Bài tập 186 CHƢƠNG 4: TRUY NHẬP CƠ SỞ DỮ LIỆU 195 4.1. Giới thiệu chung 195 4.2. Kiến trúc của ADO.NET 196 4.3. Tìm hiểu trình cung cấp dữ liệu của ADO.NET 197 4.4. Các namespace của ADO.NET 199 4.5. Các lớp thao tác với cơ sở dữ liệu 204 4.5.1. Lớp Connection 204 4.5.2. Lớp Command 209 4.5.3. Lớp DataReader 218 4.5.4. Lớp DataAdapter 222
- 4.5.5. Lớp DataSet 223 4.5.6. Lớp DataColumns 224 4.5.7. Lớp DataRow 227 4.5.8. Lớp DataTable 227 4.6. Data Binding 228 4.6.1. Giới thiệu DataBinding 228 4.6.2. Data Binding 229 4.6.3. Các điều khiển Data Source 232 4.7. Các điều khiển liên kết dữ liệu 237 4.7.1. Điều khiển GridView 237 4.7.2. Điều khiển DataList 253 4.7.3. Điều khiển Repeater 254 4.7.4. DetailView 255 4.7.5. FormView 256 4.7.6. ListView 257 4.8. Bài tập 257 CHƢƠNG 5: WEB SERVICES 266 5.1. Giới thiệu về Web Services 266 5.2. Kiến trúc và các thành phần Web Services 266 5.3. Tạo Web Services 270 5.4. Kiểm tra Web Services 271 5.5. Sử dụng Web Services 272 5.5.1. Sử dụng Web Services do mình tạo 272 5.5.2. Sử dụng Web Services đƣợc cung cấp trên mạng 276 5.6. Bài tập 279 TÀI LIỆU THAM KHẢO 281
- LỜI NÓI ĐẦU Ngày nay việc sử dụng Internet và các dịch vụ trên Internet là một phần tất yếu của cuộc sống. Công nghệ Internet và các ứng dụng phát triển trên nền Web và Internet đã và đang làm cho đời sống của chung ta thay đổi. Internet là một nguồn thông tin quý giá phục vụ cho việc học tập, nghiên cứu, kinh doanh, giải trí. Vì vậy ngày càng có nhiều ứng dụng trên Internet sử dụng giao diện Web. Các công nghệ phát triển trên Internet ngày một hoàn thiện. Trên cơ sở đó, môn học Lập trình trên nền Web đã đƣợc đƣa vào giảng dạy và nghiên cứu tại các khoa, ngành tin học, toán tin, thƣơng mại điện tử hay các ngành có liên quan khác trong các trƣờng đại học. Môn học này sẽ là tiền đề cung cấp cho sinh viên và các nhà nghiên cứu các lý thuyết từ cơ sở cho đến ứng dụng nhằm xây dựng và xử lý thông tin dƣới dạng trang Web, nhờ đó cho phép họ tiếp cận dễ dàng hơn với các kỹ thuật lập trình hiệu quả các ứng dụng trên nền Web và Internet. Tập bài giảng này nghiên cứu về công nghệ phổ biến và tiên tiến nhất đƣợc dùng đề tạo các ứng dụng chạy trên nền Web của MicroSoft là ASP.NET, ngôn ngữ lập trình C#, truy xuất dữ liệu qua ADO.NET và Web Services đáp ứng đƣợc việc học tập và nghiên cứu của sinh viên Đại học, Cao đẳng ngành Công nghệ thông tin và Khoa học máy tính Trƣờng Đại học Sƣ phạm kỹ thuật Nam Định. Tập bài giảng gồm 5 chƣơng Chƣơng 1: Tổng quan về ASP.NET Chƣơng 2: Ngôn ngữ lập trình C# Chƣơng 3: Làm việc với Web Form Chƣơng 4: Truy nhập cơ sở dữ liệu Chƣơng 5: Web Services Nội dung các chƣơng cung cấp kiến thức về thiết kế và lập trình xử lý dữ liệu Web dựa trên công cụ Visul Studio .Net. Sau mỗi phần có các ví dụ giúp sinh viên dễ tiếp cận và nắm bắt vấn đề. Cuối mỗi chƣơng đều có bài tập giúp cho sinh viên ôn tập và hệ thống kiến thức môn học. Trong quá trình biên soạn nhóm chúng tôi đã bám sát chƣơng trình môn học đƣợc nhà trƣờng ban hành, đã cố gắng thể hiện nội dung cơ bản, hiện đại gắn gắn với yêu cầu thực tế. Tuy nhiên do khả năng có hạn, hạn chế về thời gian nên không tránh khỏi sai sót. Rất mong nhận đƣợc sự đóng góp chân thành của đồng nghiệp và bạn đọc để tập bài giảng ngày càng hoàn thiện hơn. NHÓM TÁC GIẢ
- CHƢƠNG 1: TỔNG QUAN VỀ ASP.NET 1.1. Giới thiệu tổng quan về công nghệ .NET 1.1.1. Sự ra đời của .NET Trong lĩnh vực phát triển phần mềm có rất nhiều ngôn ngữ lâp trình đƣợc sử dụng để phát triển (nhƣ Delphi, Ada, Cobol, Fortran, Basic, LISP, Prolog, Foxpro, Java, Pascal, C/C++, VB.NET, VC++, C# ). Mỗi ngôn ngữ đều có những ƣu và nhƣợc điểm riêng. Những ƣu điểm có tính đặc thù của từng ngôn ngữ là điều đã đƣợc khẳng định. Tuy nhiên, rất khó để có thể tận dụng đƣợc sức mạnh của tất cả các ngôn ngữ lập trình trong một dự án phần mềm, chẳng hạn không thể hoặc rất khó khăn để viết một ứng dụng có sử dụng đồng thời cả ngôn ngữ Visual Basic và Java hay Foxpro với Delphi v.v Nói cách khác, việc “liên thông” giữa các ngôn ngữ là gần nhƣ không thể. Cũng do sự khác biệt giữa các ngôn ngữ lập trình mà việc tiếp cận hay chuyển đổi sang ngôn ngữ lập trình mới sẽ tốn rất nhiều thời gian. Vì vậy, khi các dự án sử dụng ngôn ngữ lập trình khác nhau thì chi phí cho chuyển đổi sẽ là rất lớn gây lãng phí thời gian không cần thiết và chất lƣợng phần mềm chắc chắn không cao. Từ những hạn chế trong quá trình phát triển phần mềm nhƣ đã nêu, đòi hỏi phải có một cách tiếp cận sao cho tối ƣu nhất, vừa đảm bảo tốn ít chi phí chuyển đổi vừa đảm bảo nhiều ngƣời có thể tham gia cùng một dự án mà không nhất thiết phải viết trên cùng một ngôn ngữ lập trình, đồng thời ứng dụng phải hoạt động tốt trong môi trƣờng mạng Internet. Đó chính là lý do để Microsoft cho ra công nghệ phát triển phần mềm mới .NET. 1.1.2. .NET Framework Thông thƣờng, mỗi ngôn ngữ lập trình đều có một tập các thƣ viện riêng, chẳng hạn: VC++ thì có thƣ viện chính là msvcrt.dll; Visual Basic thì có svbvm60.dll Các thƣ viện này chứa các hàm, thủ tục cơ bản của mỗi ngôn ngữ. Tất cả đều có ý nghĩa logic giống nhau nhƣng về cách sử dụng hay cú pháp thì hầu nhƣ là khác nhau. Ý tƣởng của Microsoft là không xây dựng một tập thƣ viện riêng biệt cho từng ngôn ngữ lập trình mà sẽ xây dựng một bộ thƣ viện dùng chung. Tập thƣ viện dùng chung này hình thành nên một bộ khung (Framework). Bộ Khung này thực chất là một tập các thƣ viện đƣợc xây dựng sẵn, đáp ứng mọi nhu cầu phát triển các ứng dụng Desktop, Network, Mobile, Web
- Hình 1.1. Mô hình xây dựng phần mềm bằng ngôn ngữ truyền thống Các thành phần và chức năng chính trong .NET Framework. Common Language Runtime (trình thực thi ngôn ngữ chung): Sau khi ứng dụng đƣợc biên dịch ra file “exe”. Nội dung của file exe này tuân theo một chuẩn/ngôn ngữ chung, dù là viết bằng C# hay VB.NET. Ngôn ngữ này gọi là ngôn ngữ chung), tiếp theo để file exe trung gian này có thể chạy đƣợc trên máy hiện hành thì cần phải đƣợc biên dịch ra mã máy tƣơng ứng. Việc biên dịch và chạy đƣợc là nhờ chƣơng trình thực thi ngôn ngữ chung – CLR (Common Language Runtime). Hình 1.2. Kiến trúc của .NET Framework Base Class Library: Là tập các thƣ viện chứa các lớp cơ bản để sử dụng trong tất cả các ngôn ngữ .NET. Ví dụ các lớp xử lý xâu, xử lý toán học ADO.NET: Là tập các thƣ viện chuyên dành cho thao tác với cơ sở dữ liệu. ASP.NET: Các thƣ viện dành cho phát triển các ứng dụng Web (Web Form). Windows Forms: Các thƣ viện dành cho phát triển các ứng dụng Windows
- Common Language Specification: Phần này có nhiệm vụ đặc tả ngôn ngữ chung để các chƣơng trình viết trên các ngôn ngữ lập trình khác nhau phải tuân theo. Nói cách khác, biên dịch các chƣơng trình viết trên các ngôn ngữ lập trình khác nhau về một ngôn ngữ thống nhất chung (Common Language). Các ngôn ngữ lập trình. Hình 1.3. Mô hình biên dịch và thực thi chƣơng trình ứng dụng .NET 1.1.3. Ƣu điểm chính của .NET Framework - Tất cả các ngôn ngữ đều thừa hƣởng một thƣ viện thống nhất. Khi sửa chữa hay nâng cấp thƣ viện này thì chỉ phải thực hiện một lần. - Cách thức phát triển ứng dụng nhất quán và tƣơng tự nhau giữa các ngôn ngữ lập trình. Có thể chuyển đổi sang ngôn ngữ lập trình .NET khác nhau một cách dễ dàng. - Viết các ứng dụng Web Form không khác nhiều so với ứng dụng Win Form. - Cung cấp một tập thƣ viện truy xuất CSDL thống nhất (ADO.NET) cho mọi ngôn ngữ .NET. - Hỗ trợ cơ chế “Write one – Run everywhere” (ciết một lần chạy mọi nơi). Một ứng dụng viết bằng .NET có thể chạy trên bất cứ hệ điều hành nào mà không cần phải sửa lại code, miễn là máy đó có cài .NET framework. - Cung cấp hệ thống kiểu chung (Common Type), do vậy đảm bảo tính thống nhất về kiểu dữ liệu giữa các ngôn ngữ lập trình. - Cho phép sử dụng nhiều ngôn ngữ lập trình trong cùng một dự án. - Kết thừa và sử dụng chéo giữa các ngôn ngữ lập trình dễ dàng nhƣ trên cùng một ngôn ngữ (có thể viết một class trên C#, sau đó kế thừa trong VB.NET và ngƣợc lại).
- - Việc triển khai (Deploy) các ứng dụng dễ dàng. Chỉ cần Copy-and-run (copy là chạy). Không cần cài đặt và tránh đƣợc “các lỗi DLL” nhƣ trƣớc đây. 1.2. Giới thiệu về ASP.NET - ASP.NET là công nghệ phát triển các ứng dụng trên nền Web, thế hệ kế tiếp của ASP (Active Server Page – Trang Web đƣợc xử lý bên phía máy chủ). ASP.NET là một thành phần nội tại (có sẵn) của .NET Framework. Vì vậy nó tận dụng đƣợc sức mạnh của .NET Framework. ASP.NET có một số ƣu điểm chính: - Có thể sử dụng để phát triển các ứng dụng Web đủ mọi kích cỡ, từ ứng dụng nhỏ nhất cho đến ứng dụng toàn doanh nghiệp (Enterprise). - Ứng dụng viết bằng ASP.NET dễ dàng tƣơng thích với nhiều loại trình duyệt khác nhau. Nhà phát triển không cần phải quan tâm nhiều đến trình duyệt nào đƣợc sử dụng để duyệt Website, điều này sẽ đƣợc framework tự render ra mã tƣơng ứng. - Khi sử dụng bộ IDE của Visual Studio, cách thức lập trình sẽ giống nhƣ lập trình Win Form. - Truy xuất dữ liệu bằng công nghệ ADO.NET có sẵn của .NET Framework. - Chạy ứng dụng cực nhanh bởi cơ chế biên dịch và Cached. - Có thể tăng tốc ứng dụng bằng cách Cache các điều khiển, các trang. - Bảo mật vƣợt trội. - Tốn ít dòng lệnh hơn so với ASP/PHP/Perl khi thực hiện cùng một công việc. - Dễ dàng bảo trì và dễ đọc hơn bởi Code và Giao diện đƣợc tách biệt. Điều này cũng giúp cho tính chuyên biệt hóa cao hơn (một ngƣời chỉ lo code phần xử lý nghiệp vụ, ngƣời khác thì chỉ lo code phần giao diện v.v ). - ASP.NET sử dụng ngôn ngữ lập trình VB.NET hoặc C# để phát triển ứng dụng. 1.3. Cài đặt Visual Studio.NET 1.3.1. Các phiên bản .NET Có nhiều phiên bản .NET Framework khác nhau đƣợc phát hành qua từng giai đoạn. - .NET Framework 1.0 phát hành vào năm 2002 - .NET Framework 1.1 phát hành vào năm 2003 - .NET Framework 2.0 phát hành vào năm 2005 - .NET Framework 3.0 phát hành vào năm 2006 - .NET Framework 3.5 phát hành vào năm 2007 - .NET Framework 4 phát hành trong năm 2010 - .NET Framework 4.5 phát hành vào năm 2012 1.3.2. Cài đặt Visual Studio.NET
- Việc cài đặt các phiên bản Visual Studio.Net có nhiều lựa chọn khác nhau về cơ bản ta tiến hành nhƣ sau: - Chuẩn bị đĩa chƣơng trình Visual Studio.Net và mã bản quyền sử dụng phần mềm - Đọc tệp tin yêu cầu phần cứng trƣớc khi cài đặt. - Chạy tệp tin setup.exe làm theo hƣớng đẫn trên màn hình trong quá trình cài đặt. 1.3.3. Giao diện Visual Studio.NET Visual Studio sử dụng IDE chung cho toàn bộ ngôn ngữ lập trình (ASP.NET, VB.NET, C#, ). Điều này đảm bảo tính nhất quán cho các ngôn ngữ trên nền .NET. Hình 1.4. Giao diện chính của môi trƣờng phát triển - Tab Design để hiển thị trang Web ở chế độ Design, tức là cho phép sửa chữa nội dung trang Web trực quan. Hình 1.5. Mở trang ở chế độ Design - Tab Source: Mở trang ở chế độ mã nguồn HTML. Tại đây ngƣời dùng có thể soạn thảo trực tiếp các thẻ HTML.
- Hình 1.6. Mở trang ở chế độ Source - Tab Split: Cho phép xem trang Web đồng thời ở cả hai chế độ. Hình 1.7. Mở trang ở 2 chế độ Design và Source
- Chuyển chế độ Design Chuyển chế độ Code Copy website lên server Hình 1.8. Mở cửa sổ soạn Code - Ngoài thao tác trực tiếp thông qua hệ thống menu, nút lệnh, ngƣời dùng còn có thể sử dụng tổ hợp các phím tắt. Ví dụ: Shift+F7 để xem ở chế độ Design, F7 xem ở chế độ Code, F4 Focus tới Properties . Menu bar Tool bar Vùng duyện các web form và code fille Các điều khiển Các thuộcthuộc tính của điều khiển Các chế độ xem Hình 1.9. Giao diện IDE của Visual Studio 1.4. Xây dựng ứng dụng Web 1.4.1. Tạo mới ứng dụng Web Vào menu File -> New Website hoặc biểu tƣợng trên thanh công cụ cửa sổ New Website xuất hiện.
- Hình 1.10. Các thành phần để tạo mới ứng dụng web 1.4.2. Lƣu ứng dụng Web - Nhấn Ctrl-S để lƣu trang hiện tại - Nhấn Ctrl-Shift-S để lƣu toàn bộ các trang. 1.4.3. Chạy ứng dụng Web Đối với ASP.NET, toàn bộ ứng dụng Web có thể biên dịch thành file nhị phân để chạy. Tuy nhiên ASP.NET cũng cho phép ngƣời dùng chạy từng trang riêng biệt. - Nhấn F5 (Hoặc biểu tƣợng trên thanh công cụ) để chạy ứng dụng và cho phép Debug trên trình duyệt. - Nhấn Ctrl-F5 để chạy ứng dụng nhƣng không cho Debug trên trình duyệt. - Trong trƣờng hợp muốn chạy chƣơng trình và gỡ rối ở mức dòng lệnh/ thủ tục thì có thể nhấn F8, Shift-F8. - Ngƣời dùng có thể chạy (Browse) trang Web bất kỳ bằng cách chọn, sau đó click chuột phải và chọn mục View In Browser (hoặc nhấn tổ hợp phím Ctrl- Shift-W). Trong trƣờng hợp có nhiều trình duyệt trong máy thì có thể chọn trình duyệt mặc định khi View In Browser bằng cách click chuột phải lên trang và chọn Browse With nhƣ hình dƣới.
- Hình 1.11. Chọn trình duyệt 1.5. Bài tập 1. Khi .NET ra đời đã đem lại những thuận lợi gì cho ngƣời lập trình ứng dụng? 2. Chỉ ra điểm giống và khác nhau giữa xây dựng phần mềm bằng ngôn ngữ truyền thống và .NET. 3. Trình bày các thành phần trong kiến trúc của .NET Framework. 4. Nêu các ƣu điểm chính của .NET Framework. 5. Kể tên các phiên bản .NET hiện có. 6. Nêu các bƣớc cài đặt Visual Studio.NET. 7. Kể tên và nêu ý nghĩa các thành phần trong giao diện Visual Studio.NET. 8. Nêu các bƣớc xây dựng ứng dụng Web.
- CHƢƠNG 2: NGÔN NGỮ LẬP TRÌNH C# 2.1. Giới thiệu về ngôn ngữ lập trình C# Ngôn ngữ C# là một ngôn ngữ đƣợc dẫn xuất từ C và C++, nhƣng nó đƣợc tạo từ nền tảng phát triển hơn. Microsoft thêm vào những đặc tính mới để làm cho ngôn ngữ này dễ sử dụng hơn, nhiều trong số những đặc tính này khá giống với những đặc tính có trong ngôn ngữ Java. Nó có một số đặc điểm cơ bản sau: - C# là ngôn ngữ đơn giản Trong C# không có sự phức tạp của những ngôn ngữ nhƣ Java và C++, bao gồm việc loại bỏ macro, template, đa kế thừa và lớp cơ sở ảo (virtual base class). Ngôn ngữ C# đơn giản nó dựa trên nền tảng C và C++ bởi C# khá giống về cú pháp, biểu thức, toán tử và những chức năng khác đƣợc lấy trực tiếp từ ngôn ngữ C và C++, nhƣng đã đƣợc cải tiến để làm cho ngôn ngữ đơn giản hơn. Một trong các cải tiến là loại bỏ các dƣ thừa, thêm những cú pháp thay đổi. - C# là ngôn ngữ hiện đại Những đặc tính nhƣ xử lý ngoại lệ, thu gom bộ nhớ tự động, những kiểu dữ liệu mở rộng và bảo mật mã nguồn là những đặc tính đƣợc mong đợi trong một ngôn ngữ hiện đại. C# chứa tất cả những đặc tính trên. - C# là ngôn ngữ hƣớng đối tƣợng Những đặc tính nhƣ xử lý ngoại lệ, thu gom bộ nhớ tự động, những kiểu dữ liệu mở rộng và bảo mật mã nguồn là những đặc tính đƣợc mong đợi trong một ngôn ngữ hiện đại. C# chứa tất cả những đặc tính trên. - C# là ngôn ngữ mạnh mẽ và mềm dẻo Ngôn ngữ C# đƣợc sử dụng cho nhiều công việc khác nhau nhƣ là tạo ra ứng dụng xử lý văn bản, ứng dụng đồ họa, hay những trình biên dịch cho các ngôn ngữ khác. - C# là ngôn ngữ ít từ khóa C# là ngôn ngữ sử dụng giới hạn những từ khóa. Phần lớn các từ khóa đƣợc sử dụng để mô tả thông tin. Bảng sau liệt kê các từ khóa của ngôn ngữ C# abstract default foreach object sizeof unsafe as delegate goto operator stackalloc ushort base do if out static using bool double implicit override string virtual
- break else in params struct volatile byte enum int private switch void case event interface protected this while catch explicit internal public throw char extern is readonly true checked false lock ref try class finally long return typeof const fixed namespace sbyte uint continue float new sealed ulong decimal for null short unchecked - C# là ngôn ngữ hƣớng module Mã nguồn C# có thể đƣợc viết trong những phần đƣợc gọi là những lớp, những lớp này chứa các phƣơng thức thành viên của nó. Những lớp và phƣơng thức có thể đƣợc sử dụng lại trong ứng dụng hay các chƣơng trình khác. Bằng cách truyền các mẫu thông tin đến những lớp hay phƣơng thức để tạo ra những mã nguồn dùng lại có hiệu quả. 2.2. Cấu trúc một chƣơng trình C# Cách tạo một project trong C#: New >> Project >> Visual C# >> Windows >> Console Application >> đặt tên và nơi lƣu; nếu check vào create directory for solution thì Visual Studio sẽ tạo ra thƣ mục chứa project. Một chƣơng trình C# đơn giản: using System; using System.Collections.Generic; using System.Text; namespace Hello { class Program { static void Main(string[] args) { Console.WriteLine("Xin chao"); Console.Read(); } } } 2.3. Các kiểu dữ liệu C# là ngôn ngữ lập trình mạnh về kiểu dữ liệu, một ngôn ngữ mạnh về kiểu dữ liệu là phải khai báo kiểu của mỗi đối tƣợng khi tạo (kiểu số nguyên, số thực, kiểu chuỗi, kiểu
- điều khiển ) và trình biên dịch giúp cho ngƣời lập trình không bị lỗi khi chỉ cho phép một loại kiểu dữ liệu có thể đƣợc gán cho các kiểu dữ liệu khác. Kiểu dữ liệu của một đối tƣợng là một tín hiệu để trình biên dịch nhận biết kích thƣớc của một đối tƣợng (kiểu int có kích thƣớc là 4 byte) và khả năng của nó (nhƣ một đối tƣợng button có thể vẽ, phản ứng khi nhấn, ). Tƣơng tự nhƣ C++ hay Java, C# chia thành hai tập hợp kiểu dữ liệu chính: Kiểu xây dựng sẵn (built- in) mà ngôn ngữ cung cấp cho ngƣời lập trình và kiểu đƣợc ngƣời dùng định nghĩa (user-defined) do ngƣời lập trình tạo ra. 2.3.1. Kiểu dữ liệu xây dựng sẵn Ngôn ngữ C# đƣa ra các kiểu dữ liệu xây dựng sẵn phù hợp với một ngôn ngữ lập trình hiện đại, mỗi kiểu dữ liệu đƣợc ánh xạ đến một kiểu dữ liệu đƣợc hỗ trợ bởi hệ thống xác nhận ngôn ngữ chung (Common Language Specification: CLS) trong MS.NET. Việc ánh xạ các kiểu dữ liệu nguyên thuỷ của C# đến các kiểu dữ liệu của .NET sẽ đảm bảo các đối tƣợng đƣợc tạo ra trong C# có thể đƣợc sử dụng đồng thời với các đối tƣợng đƣợc tạo bởi bất cứ ngôn ngữ khác đƣợc biên dịch bởi .NET, nhƣ VB.NET. Mỗi kiểu dữ liệu có một sự xác nhận và kích thƣớc không thay đổi, không giống nhƣ C++, int trong C# luôn có kích thƣớc là 4 byte bởi vì nó đƣợc ánh xạ từ kiểu Int32 trong .NET. Bảng sau sẽ mô tả một số các kiểu dữ liệu đƣợc xây dựng sẵn Kiểu C# Số byte Kiểu .NET Mô tả byte 1 Byte Số nguyên dƣơng không dấu từ 0-255 char 2 Char Ký tự Unicode bool 1 Boolean Giá trị logic true/ false sbyte 1 Sbyte Số nguyên có dấu ( từ -128 đến 127) short 2 Int16 Số nguyên có dấu giá trị từ -32768 đến 32767. ushort 2 Uịnt16 Số nguyên không dấu 0 – 65.535 int 4 Int32 Số nguyên có dấu –2.147.483.647 và 2.147.483.647 uint 4 Uint32 Số nguyên không dấu 0 – 4.294.967.295 float 4 Single Kiểu dấu chấm động, giá trị xấp xỉ từ 3,4E- 38 đến 3,4E+38, với 7 chữ số có nghĩa
- double 8 Double Kiểu dấu chấm động có độ chính xác gấp đôi, giá trị xấp xỉ từ 1,7E-308 đến 1,7E+308, với 15,16 chữ số có nghĩa. decimal 8 Decimal Có độ chính xác đến 28 con số và giá trị thập phân, đƣợc dùng trong tính toán tài chính, kiểu này đòi hỏi phải có hậu tố “m” hay “M” theo sau giá trị. long 8 Int64 Kiểu số nguyên có dấu có giá trị trong khoảng : -9.223.370.036.854.775.808 đến 9.223.372.036.854.775.807 ulong 8 Uint64 Số nguyên không dấu từ 0 đến 0xffffffffffffffff 2.3.2. Chọn kiểu dữ liệu Thông thƣờng để chọn một kiểu dữ liệu nguyên để sử dụng nhƣ short, int hay long thƣờng dựa vào độ lớn của giá trị muốn sử dụng. Ví dụ, một biến ushort có thể lƣu giữ giá trịtừ 0 đến 65.535, trong khi biến ulong có thể lƣu giữ giá trị từ 0 đến 4.294.967.295, do đó tùy vào miền giá trị của phạm vi sử dụng biến mà chọn các kiểu dữ liệu thích hợp nhất. Kiểu dữ liệu int thƣờng đƣợc sử dụng nhiều nhất trong lập trình vì với kích thƣớc 4 byte của nó cũng đủ để lƣu các giá trị nguyên cần thiết. Kiểu float, double và decimal đƣa ra nhiều mức độ khác nhau về kích thƣớc cũng nhƣ độ chính xác. Với thao tác trên các phân số nhỏ thì kiểu float là thích hợp nhất. Tuy nhiên lƣu ý rằng trình biên dịch luôn luôn hiểu bất cứ một số thực nào cũng là một số kiểu double trừ khi khai báo rõ ràng. Để gán một số kiểu float thì số phải có ký tự f theo sau. float soFloat = 24f; Kiểu dữ liệu ký tự thể hiện các ký tự Unicode, bao gồm các ký tự đơn giản, ký tự theo mã Unicode và các ký tự thoát khác đƣợc bao trong những dấu nháy đơn. Ví dụ, A là một ký tự đơn giản trong khi \u0041 là một ký tự Unicode. Ký tự thoát là những ký tự đặc biệt bao gồm hai ký tự liên tiếp trong đó ký tự đầu tiên là dấu chéo „\‟. Ví dụ, \t là dấu tab. Bảng sau trình bày các ký tự đặc biệt. Ký tự Ý nghĩa \‟ Dấu nháy đơn „ \” Dấu nháy kép
- \\ Dấu chéo \0 Ký tự null \a Alert \b Backspace \f Sang trang form feed \n Dòng mới \r Đầu dòng \t Tab ngang \v Tab dọc 2.3.3. Chuyển đổi kiểu dữ liệu Những đối tƣợng của một kiểu dữ liệu này có thể đƣợc chuyển sang những đối tƣợng của một kiểu dữ liệu khác thông qua cơ chế chuyển đổi tƣờng minh hay ngầm định. Chuyển đổi ngầm định đƣợc thực hiện một cách tự động, trình biên dịch sẽ thực hiện công việc này. Còn chuyển đổi tƣờng minh diễn ra khi gán ép một giá trị cho kiểu dữ liệu khác. Việc chuyển đổi giá trị ngầm định đƣợc thực hiện một cách tự động và đảm bảo là không mất thông tin. Ví dụ, có thể gán ngầm định một số kiểu short (2 byte) vào một số kiểu int (4 byte) một cách ngầm định. Sau khi gán hoàn toàn không mất dữ liệu vì bất cứ giá trị nào của short cũng thuộc về int: short x = 10; int y = x; // chuyển đổi ngầm định Tuy nhiên, nếu thực hiện chuyển đổi ngƣợc lại, chắc chắn sẽ bị mất thông tin. Nếu giá trị của số nguyên đó lớn hơn 32.767 thì nó sẽ bị cắt khi chuyển đổi. Trình biên dịch sẽ không thực hiện việc chuyển đổi ngầm định từ số kiểu int sang số kiểu short: short x; int y = 100; x = y; // Không biên dịch, lỗi Để không bị lỗi dùng lệnh gán tƣờng minh, đoạn mã trên đƣợc viết lại nhƣ sau: short x; int y = 500; x = (short) y; // Ép kiểu tường minh, trình biên dịch không báo lỗi 2.3.4. Kiểu dữ liệu mảng Mảng là một tập hợp có thứ tự của những đối tƣợng, tất cả các đối tƣợng này cùng một kiểu. Mảng trong ngôn ngữ C# có một vài sự khác biệt so với mảng trong
- ngôn ngữ C++ và một số ngôn ngữ khác, bởi vì chúng là những đối tƣợng. Điều này sẽ cung cấp cho mảng sử dụng các phƣơng thức và những thuộc tính. Ngôn ngữ C# cung cấp cú pháp chuẩn cho việc khai báo những đối tƣợng Array. Tuy nhiên, cái thật sự đƣợc tạo ra là đối tƣợng của kiểu System.Array. Mảng trong ngôn ngữ C# kết hợp cú pháp khai báo mảng theo kiểu ngôn ngữ C và kết hợp với định nghĩa lớp do đó thể hiện của mảng có thể truy cập những phƣơng thức và thuộc tính của System.Array. Để khai báo một mảng trong C# sử dụng cú pháp nhƣ sau: [] Trong đó: DataType: kiểu dữ liệu như int, float . ArrayName: tên mảng [ ]: cặp dấu ngoặc vuông chỉ ra cho trình biên dịch biết đang khai báo một mảng. Ví dụ: Khai báo mảng số nguyên int[] x; Khởi tạo giá trị cho mảng: Cách 1: Khai báo và chỉ ra số phần tử của mảng Cú pháp: [DataType] [ ] [ArrayName] = new [DataType] [number of elements]; Trong đó: number of elements: số phần tử của mảng. Ví dụ: Khai báo một mảng số nguyên lƣu trữ 5 phần tử. int[] a = new int[5] Cách 2: Khai báo sau đó mới khởi tạo số phần tử của mảng. Cú pháp: [DataType] [ ] [ArrayName]; [ArrayName] = new [DataType] [number of elements]; Ví dụ: Khai báo một mảng số nguyên lƣu trữ 5 phần tử. int[] a; a = new int[5]; Cách 3: Khai báo, chỉ ra số lƣợng các phần tử mảng và gán các giá trị ban đầu cho các phần tử mảng. Cú pháp: [DataType] [ ] [ArrayName]= new [DataType] [number of elements]{value}; Ví dụ khai báo mảng int[] a = new int[5] {1, -1, 3, 4, 5}; Cách 4: Khai báo, không chỉ ra số lƣợng các phần tử mảng và gán giá trị cho các phần tử của mảng. Truy cập các phần tử mảng: Một mảng là một danh sách các phần tử có cùng kiểu dữ liệu, các phần tử đó đƣợc đánh số thứ tự bắt đầu từ 0 đến n-1 (trong đó n là số phần tử
- của mảng). Nhƣ vậy để truy cập đến 1 phần tử của mảng thì ta sử dụng một số nguyên để chỉ ra số thứ tự của phần tử đó trong mảng, phần tử nguyên này đƣợc gọi là chỉ số (index). Cú pháp tổng quát để truy cập đến phần tử thứ i của mảng là: [tên mảng] [i-1]; Ví dụ: Gán giá trị 5 cho phần tử thứ 3 của mảng a[2] = 5; Duyệt qua các phần tử mảng: Mảng là một tập hợp hữu hạn phần tử do đó để duyệt qua các phần tử mảng thƣờng sử dụng vòng lặp for. Ví dụ: In danh sách các phần tử của mảng a ở trên. Console.WriteLine("Danh sach cac phan tu trong mang:"); for (int i = 0; i ; Hoặc: = ; Ví dụ về khai báo biến class MinhHoaBien { static void Main() { int bien1 = 9; Console.WriteLine(“Sau khi khoi tao: bien1 =”, bien1); bien1 = 15; Console.WriteLine(“Sau khi gan: bien1 =”, bien1); } }
- - Khai báo hằng Hằng là một biến nhƣng giá trị của nó không thay đổi. Cú pháp: = ; Ví dụ khai báo hằng const int x = 100; 2.5. Biểu thức và toán tử Những câu lệnh mà thực hiện việc đánh giá một giá trị gọi là biểu thức. Một phép gán một giá trị cho một biến cũng là một biểu thức: var1 = 24; Toán tử đƣợc kí hiệu bằng một biểu tƣợng dùng để thực hiện một hành động. Các kiểu dữ liệu cơ bản của C# nhƣ kiểu nguyên hỗ trợ rất nhiều các toán tử nhƣ toán tử gán, toán tử toán học, logic Toán tử gán: Toán tử gán hay phép gán làm cho toán hạng bên trái thay đổi giá trị bằng với giá trị của toán hạng bên phải. Toán tử toán học: Ngôn ngữ C# cung cấp năm toán tử toán học, bao gồm bốn toán tử đầu các phép toán cơ bản (+,-,*,/) và phép toán chia lấy dƣ (%) Toán tử tăng và giảm Toán tử Ý nghĩa x+=y Cộng thêm giá trị toán hạng bên phải vào giá trị toán hạng bên trái -= Toán hạng bên trái đƣợc trừ bớt đi một lƣợng bằng giá trị của toán hạng bên phải *= Toán hạng bên trái đƣợc nhân với một lƣợng bằng giá trị của toán hạng bên phải. /= Toán hạng bên trái đƣợc chia với một lƣợng bằng giá trị của toán hạng bên phải. %= Toán hạng bên trái đƣợc chia lấy dƣ với một lƣợng bằng giá trị của toán hạng bên phải. Toán tử quan hệ Tên toán tử Kí hiệu Biểu thức so sánh Kết quả so sánh So sánh bằng == value1 == 100 true value1 == 50 false Không bằng != value2 != 100 false value2 != 90 true
- Lớn hơn > value1 > value2 true value2 > value1 false Lớn hơn hay bằng >= value2 >= 50 true Nhỏ hơn else Câu lệnh rẽ nhánh if else dựa trên một điều kiện. Điều kiện là một biểu thức sẽ đƣợc kiểm tra giá trị ngay khi bắt đầu gặp câu lệnh đó. Nếu điều kiện đƣợc kiểm tra đúng, thì câu lệnh hay một khối các câu lệnh bên trong thân của câu lệnh if đƣợc thực hiện. Trong câu lệnh rẽ nhánh if else thì else là phần tùy chọn. Các câu lệnh bên trong thân của else chỉ đƣợc thực hiện khi điều kiện của if là sai. Do vậy khi câu lệnh đầy đủ if else đƣợc dùng thì chỉ có một trong hai if hoặc else đƣợc thực hiện. Nếu các câu lệnh trong thân của if hay else mà lớn hơn một lệnh thì các lệnh này phải đƣợc bao trong một khối lệnh, tức là phải nằm trong dấu khối { }: if (biểu thức điều kiện) { } else {
- } Ví dụ: Dùng câu lệnh điều kiện if else using System; class ExIfElse { static void Main() { int var1 = 10; int var2 = 20; if ( var1 > var2) { Console.WriteLine( “var1: {0} > var2:{1}”, var1, var2); } else { Console.WriteLine( “var2: {0} > var1:{1}”, var2, var1); } var1 = 30; if ( var1 > var2) { var2 = var1++; Console.WriteLine( “Gan gia tri var1 cho var2”); Console.WriteLine( “Tang bien var1 len mot ”); Console.WritelLine( “Var1 = {0}, var2 = {1}”, var1, var2); } else { var1 = var2; Console.WriteLine( “Thiet lap gia tri var1 = var2” ); Console.WriteLine( “var1 = {0}, var2 = {1}”, var1, var2 ); } } } b) Câu lệnh if lồng nhau Các lệnh điều kiện if có thể lồng nhau để phục vụ cho việc xử lý các câu điều kiện phức tạp. Việc này cũng thƣờng xuyên gặp khi lập trình. Giả sử cần viết một chƣơng
- trình có yêu cầu xác định tình trạng kết hôn của một công dân dựa vào các thông tin nhƣ tuổi, giới tính và tình trạng hôn nhân, dựa trên một số thông tin nhƣ sau: - Nếu công dân là nam thì độ tuổi kết hôn là 20 với điều kiện là chƣa có gia đình. - Nếu công dân là nữ thì độ tuổi kết hôn là 19 cũng với điều kiện là chƣa có gia đình. - Tất cả các công dân có tuổi nhỏ hơn 19 điều không đƣợc kết hôn. Dựa trên các yêu cầu trên ta có thể dùng các lệnh if lồng nhau để thực hiện. Ví dụ: Các lệnh if lồng nhau using System; class TinhTrangKetHon { static void Main(){ int tuoi; bool coGiaDinh; // 0: chưa có gia đình; 1: đã có gia đình bool gioiTinh; // 0: giới tính nữ; 1: giới tính nam tuoi = 24; coGiaDinh = false; // chưa có gia đình gioiTinh = true; // nam if ( tuoi >= 19) { if ( coGiaDinh == false){ if ( gioiTinh == false) // nu Console.WriteLine(“ Nu co the ket hon”); else // nam if (tuoi >19) // phải lớn hơn 19 tuoi mới được kết hôn Console.WriteLine(“ Nam co the ket hon”); } else // da co gia dinh Console.WriteLine(“ Khong the ket hon nua do da ket hon”); } else // tuoi < 19 Console.WriteLine(“ Khong du tuoi ket hon” ); } } c) Câu lệnh switch Khi có quá nhiều điều kiện để chọn thực hiện thì dùng câu lệnh if sẽ phức tạp, Các ngôn ngữ lập trình cấp cao cung cấp một dạng câu lệnh switch liệt kê các giá trị và chỉ thực hiện các giá trị thích hợp. C# cung cấp câu lệnh nhảy switch có cú pháp nhƣ sau:
- switch (biểu thức điều kiện) { case : case : default: } Cũng tƣơng tự nhƣ câu lệnh if, biểu thức để so sánh đƣợc đặt sau từ khóa switch, tuy nhiên giá trị so sánh lại đƣợc đặt sau mỗi các từ khóa case. Giá trị sau từ khóa case là các giá trị hằng số nguyên. Nếu một câu lệnh case đƣợc thích hợp tức là giá trị sau case bằng với giá trị của biểu thức sau switch thì các câu lệnh liên quan đến câu lệnh case này sẽ đƣợc thực thi. Tuy nhiên phải có một câu lệnh nhảy nhƣ break, goto để điều khiển nhảy qua các case khác. Vì nếu không có các lệnh nhảy này thì khi đó chƣơng trình sẽ thực hiện tất cả các case theo sau. Để dễ hiểu hơn ta sẽ xem xét ví dụ dƣới đây. Ví dụ: Câu lệnh switch using System; class MinhHoaSwitch { static void Main() { const int mauDo = 0; const int mauCam = 1; const int mauVang = 2; const int mauLuc = 3; const int mauLam = 4; const int mauCham = 5; const int mauTim = 6; int chonMau = mauLuc; switch ( chonMau ) { case mauDo: Console.WriteLine( “Ban cho mau do” );
- break; case mauCam: Console.WriteLine( “Ban cho mau cam” ); break; case mauVang: Console.WriteLine( “Ban chon mau vang”); break; case mauLuc: Console.WriteLine( “Ban chon mau luc”); break; case mauLam: Console.WriteLine( “Ban chon mau lam”); goto case mauCham; case mauCham: Console.WriteLine( “Ban cho mau cham”); goto case mauTim; case mauTim: Console.WriteLine( “Ban chon mau tim”); goto case mauLuc; default: Console.WriteLine( “Ban khong chon mau nao het”); break; } Console.WriteLine( “Xin cam on!”); } } Trong C# không thể nhảy xuống một trƣờng hợp case tiếp theo nếu câu lệnh case hiện tại không rỗng. Vì vậy phải viết nhƣ sau: case 1: // nhảy xuống case 2: Nhƣ minh họa trên trƣờng hợp xử lý case 1 là rỗng, tuy nhiên không thể viết: case 1: DoAnything(); // Trường hợp này không thể nhảy xuống case 2 case 2:
- Trong đoạn chƣơng trình thứ hai trƣờng hợp case 1 có một câu lệnh nên không thể nhảy xuống đƣợc. Nếu muốn trƣờng hợp case1 nhảy qua case 2 thì ta phải sử dụng câu lệnh goto một cách tƣờng minh: case 1: DoAnything(); goto case 2; case 2: Do vậy khi thực hiện xong các câu lệnh của một trƣờng hợp nếu muốn thực hiện một trƣờng hợp case khác thì ta dùng câu lệnh nhảy goto với nhãn của trƣờng hợp đó: goto case Khi gặp lệnh thoát break thì chƣơng trình thoát khỏi switch và thực hiện lệnh tiếp sau khối switch đó. Nếu không có trƣờng hợp nào thích hợp và trong câu lệnh switch có dùng câu lệnh defalut thì các câu lệnh của trƣờng hợp default sẽ đƣợc thực hiện. Ta có thể dùng default để cảnh báo lỗi hay xử lý một trƣờng hợp ngoài tất cả các trƣờng hợp case trong switch. Trong ví dụ minh họa câu lệnh switch đầu tiên thì giá trị để kiểm tra các trƣờng hợp thích hợp là các hằng số nguyên. Tuy nhiên C# còn có khả năng cho phép dùng câu lệnh switch với giá trị là một chuỗi, có thể viết nhƣ sau: switch (chuoi1) { case “mau do”: break; case “mau cam”: break; } 2.6.2. Các câu lệnh lặp C# cung cấp một bộ mở rộng các câu lệnh lặp, bao gồm các câu lệnh lặp for, while và do while. Ngoài ra ngôn ngữ C# còn bổ sung thêm một câu lệnh lặp foreach. Cuối cùng là các câu lệnh nhảy nhƣ goto, break, continue và return. a) Câu lệnh nhảy goto Lệnh nhảy goto là một lệnh nhảy đơn giản, cho phép chƣơng trình nhảy vô điều kiện tới một vị trí trong chƣơng trình thông qua tên nhãn. Tuy nhiên việc sử dụng lệnh goto thƣờng làm mất đi tính cấu trúc thuật toán, việc lạm dụng sẽ dẫn đến một chƣơng trình nguồn bị rối. Nên hạn chế dùng lệnh goto. Sau đây là cách sử dụng lệnh nhảy goto: Tạo một nhãn goto đến nhãn
- Nhãn là một định danh theo sau bởi dấu hai chấm (:). Thƣờng thƣờng một lệnh goto gắn với một điều kiện nào đó, ví dụ sau sẽ minh họa các sử dụng lệnh nhảy goto trong chƣơng trình. Ví dụ: Sử dụng goto using System; public class UsingGoto { public static int Main(){ int i = 0; lap: // nhãn Console.WriteLine(“i:{0}”,i); i++; if ( i Biểu thức của vòng lặp while là điều kiện để các lệnh đƣợc thực hiện, biểu thức này bắt buộc phải trả về một giá trị kiểu bool là true/false. Nếu có nhiều câu lệnh cần đƣợc thực hiện trong vòng lặp while thì phải đặt các lệnh này trong khối lệnh. Ví dụ: Sử dụng vòng lặp while using System; public class UsingWhile { public static int Main(){ int i = 0; while ( i < 10 ){ Console.WriteLine(“ i: {0} ”,i); i++; } return 0; } }
- Vòng lặp while kiểm tra điều kiện trƣớc khi thực hiện các lệnh bên trong, điều này đảm bảo nếu ngay từ đầu điều kiện sai thì vòng lặp sẽ không bao giờ thực hiện. Do vậy nếu khởi tạo biến i có giá trị là 11, thì vòng lặp sẽ không đƣợc thực hiện. c) Vòng lặp do while Đôi khi vòng lặp while không thoả mãn yêu cầu trong tình huống muốn chuyển ngữ nghĩa của while là “chạy trong khi điều kiện đúng” thành ngữ nghĩa khác nhƣ “làm điều này trong khi điều kiện vẫn còn đúng”. Nói cách khác thực hiện một hành động và sau khi hành động đƣợc hoàn thành thì kiểm tra điều kiện. Cú pháp sử dụng vòng lặp do while nhƣ sau: do while ( điều kiện ) Ở đây có sự khác biệt quan trọng giữa vòng lặp while và vòng lặp do while là khi dùng vòng lặp do while thì tối thiểu sẽ có một lần các câu lệnh trong do while đƣợc thực hiện. Điều này cũng dễ hiểu vì lần đầu tiên đi vào vòng lặp do while thì điều kiện chƣa đƣợc kiểm tra. Ví dụ: Sử dụng vòng lặp do while using System; public class UsingDoWhile { public static int Main( ) { int i = 11; do { Console.WriteLine(“i: {0}”,i);i++; } while ( i < 10 ) return 0; } } Do khởi tạo biến i giá trị là 11, nên điều kiện của while là sai, tuy nhiên vòng lặp do while vẫn đƣợc thực hiện một lần. d) Vòng lặp for Vòng lặp for bao gồm ba phần chính: - Khởi tạo biến đếm vòng lặp - Kiểm tra điều kiện biến đếm, nếu đúng thì thực hiện các lệnh bên trong vòng for
- - Thay đổi bƣớc lặp. Cú pháp sử dụng vòng lặp for nhƣ sau: for ([ phần khởi tạo] ; [biểu thức điều kiện]; [bước lặp]) Ví dụ: Sử dụng vòng lặp for using System; public class UsingFor { public static int Main(){ for (int i = 0; i in ) Do lặp dựa trên một mảng hay tập hợp nên toàn bộ vòng lặp sẽ duyệt qua tất cả các thành phần của tập hợp theo thứ tự đƣợc sắp. Khi duyệt đến phần tử cuối cùng trong tập hợp thì chƣơng trình sẽ thoát ra khỏi vòng lặp foreach. Ví dụ: Sử dụng vòng lặp foreach using System; public class UsingForeach { public static int Main(){ int[] intArray = {1,2,3,4,5,6,7,8,9,10}; foreach( int item in intArray){
- Console.Write(“{0} ”, item); } return 0; } } f) Câu lệnh nhảy break và continue Khi đang thực hiện các lệnh trong vòng lặp, có yêu cầu nhƣ sau: không thực hiện các lệnh còn lại nữa mà thoát khỏi vòng lặp, hay không thực hiện các công việc còn lại của vòng lặp hiện tại mà nhảy qua vòng lặp tiếp theo. Để đáp ứng yêu cầu trên C# cung cấp hai lệnh nhảy là break và continue để thoát khỏi vòng lặp. Break khi đƣợc sử dụng sẽ đƣa chƣơng trình thoát khỏi vòng lặp và tiếp tục thực hiện các lệnh tiếp ngay sau vòng lặp. Continue ngừng thực hiện các công việc còn lại của vòng lặp hiện thời và quay về đầu vòng lặp để thực hiện bƣớc lặp tiếp theo. Hai lệnh break và continue tạo ra nhiều điểm thoát và làm cho chƣơng trình khó hiểu cũng nhƣ là khó duy trì. Do vậy phải cẩn trọng khi sử dụng các lệnh nhảy này. 2.7. Xây dựng lớp và đối tƣợng 2.7.1. Xây dựng lớp Để định nghĩa một kiểu dữ liệu mới hay một lớp đầu tiên phải khai báo rồi sau đó mới định nghĩa các thuộc tính và phƣơng thức của kiểu dữ liệu đó. Khai báo một lớp bằng cách sử dụng từ khoá class. Cú pháp đầy đủ của khai báo một lớp nhƣ sau: [Thuộc tính] class { } Chú ý: Trong ngôn ngữ C# phần kết thúc của lớp không có đấu chấm phẩy giống nhƣ khai báo lớp trong ngôn ngữ C/C++. Tuy nhiên nếu ngƣời lập trình thêm vào thì trình biên dịch C# vẫn chấp nhận mà không đƣa ra cảnh báo lỗi. Trong C#, các hàm điều đƣợc đƣa vào trong một lớp, kể cả hàm đầu vào của chƣơng trình (hàm Main()): public class Tester { public static int Main(){ // } }
- Điều cần nói ở đây là chƣa tạo bất cứ thể hiện nào của lớp, tức là tạo đối tƣợng cho lớp Tester. Điều gì khác nhau giữa một lớp và thể hiện của lớp? Để trả lới cho câu hỏi này bắt đầu xem xét sự khác nhau giữa kiểu dữ liệu int và một biến kiểu int. Ta viết nhƣ sau: int var1 = 10; Tuy nhiên ta không thể viết đƣợc int = 10; Ta không thể gán giá trị cho một kiểu dữ liệu, thay vào đó ta chỉ đƣợc gán dữ liệu cho một đối tƣợng của kiểu dữ lịêu đó, trong trƣờng hợp trên đối tƣợng là biến var1. Khi tạo một lớp mới, đó chính là việc định nghĩa các thuộc tính và hành vi của tất cả các đối tƣợng của lớp. Giả sử đang lập trình để tạo các điều khiển trong các ứng dụng trên Windows, các điều khiển này giúp cho ngƣời dùng tƣơng tác tốt với Windows, nhƣ là ListBox, TextBox, ComboBox, Một trong những điều khiển thông dụng là ListBox, điều khiển này cung cấp một danh sách liệt kê các mục chọn và cho phép ngƣời dùng chọn các mục tin trong đó. ListBox này cũng có các thuộc tính khác nhau nhƣ: chiều cao, bề dày, vị trí và màu sắc và các hành vi của chúng nhƣ: chúng có thể thêm bớt mục tin, sắp xếp, Ngôn ngữ lập trình hƣớng đối tƣợng cho phép tạo kiểu dữ liệu mới là lớp ListBox, lớp này bao bọc các thuộc tính cũng nhƣ khả năng nhƣ: các thuộc tính height, width, location, color, các phƣơng thức hay hành vi nhƣ Add(), Remove(), Sort(), Không thể gán dữ liệu cho kiểu ListBox, thay vào đó đầu tiên ta phải tạo một đối tƣợng cho lớp đó: ListBox myListBox; Khi đã tạo một thể hiện của lớp ListBox thì ta có thể gán dữ liệu cho thể hiện đó. Tuy nhiên đoạn lệnh trên chƣa thể tạo đối tƣợng trong bộ nhớ đƣợc. Bây giờ ta sẽ tìm hiểu cách tạo một lớp và tạo các thể hiện thông qua ví dụ minh họa. Ví dụ này tạo một lớp có chức năng hiểu thị thời gian trong một ngày. Lớp này có hành vi thể hiện ngày, tháng, năm, giờ, phút, giây hiện hành. Để làm đƣợc điều trên thì lớp này có 6 thuộc tính hay còn gọi là biến thành viên, cùng với một phƣơng thức nhƣ sau: Ví dụ: Tạo một lớp Thoigian using System; public class ThoiGian { public void ThoiGianHienHanh(){ Console.WriteLine(“Hien thi thoi gian hien hanh”); }
- int Nam; int Thang; int Ngay; int Gio; int Phut; int Giay; } public class Tester { static void Main() { ThoiGian t = new ThoiGian(); t.ThoiGianHienHanh(); } } Lớp ThoiGian chỉ có một phƣơng thức chính là hàm ThoiGianHienHanh(), phần thân của phƣơng thức này đƣợc định nghĩa bên trong của lớp ThoiGian. Điều này khác với ngôn ngữ C++, C# không đòi hỏi phải khai báo trƣớc khi định nghĩa một phƣơng thức và cũng không hỗ trợ việc khai báo phƣơng thức trong một tập tin và sau đó định nghĩa ở một tập tin khác. C# không có các tập tin tiêu đề, do vậy tất cả các phƣơng thức đƣợc định nghĩa hoàn toàn bên trong của lớp. Phần cuối của định nghĩa lớp là phần khai báo các biến thành viên: Nam, Thang, Ngay, Gio, Phut, va Giay. Sau khi định nghĩa xong lớp ThoiGian, thì tiếp theo là phần định nghĩa lớp Tester, lớp này có chứa một hàm là hàm Main(). Bên trong hàm Main có một thể hiện của lớp ThoiGian đƣợc tạo ra và gán giá trị cho đối tƣợng t. Bởi vì t là thể hiện của đối tƣợng ThoiGian, nên hàm Main() có thể sử dụng phƣơng thức của t: t.ThoiGianHienHanh(); Thuộc tính truy cập: Thuộc tính truy cập quyết định các phƣơng thức của lớp bao gồm việc các phƣơng thức của lớp khác có thể nhìn thấy và sử dụng các biến thành viên hay những phƣơng thức bên trong lớp. Bảng sau tóm tắt các thuộc tính truy cập của một lớp trong C#. Thuộc tính Giới hạn truy cập public Không hạn chế. Những thành viên đƣợc đánh dấu public có thể đƣợc dùng bởi bất kì các phƣơng thức của lớp bao gồm những lớp khác.
- private Thành viên trong một lớp A đƣợc đánh dấu là private thì chỉ đƣợc truy cập bởi các phƣơng thức của lớp A. protected Thành viên trong lớp A đƣợc đánh dấu là protected thì chỉ đƣợc các phƣơng thức bên trong lớp A và những phƣơng thức dẫn xuất từ lớp A truy cập. internal Thành viên trong lớp A đƣợc đánh dấu là internal thì đƣợc truy cập bởi những phƣơng thức của bất cứ lớp nào trong cùng khối hợp ngữ với A. protected internal Thành viên trong lớp A đƣợc đánh dấu là protected internal đƣợc truy cập bởi các phƣơng thức của lớp A, các phƣơng thức của lớp dẫn xuất của A và bất cứ lớp nào trong cùng khối hợp ngữ của A. C# xem thuộc tính private là mặc định nên các biến thành viên của lớp ở thuộc tính private. Khi đó chỉ có phƣơng thức thành viên của lớp truy cập đƣợc giá trị của biến. Vì vậy ta không khai báo thuộc tính truy cập cho 6 biến nên mặc định chúng là private: // Các biến thành viên private int Nam; int Thang; int Ngay; int Gio; int Phut; int Giay; Do lớp Tester và phƣơng thức thành viên ThoiGianHienHanh của lớp ThoiGian đƣợc khai báo là public nên bất kỳ lớp nào cũng có thể truy cập đƣợc. Tham số của phƣơng thức: Trong các ngôn ngữ lập trình thì tham số và đối mục đƣợc xem là nhƣ nhau, cũng tƣơng tự khi đang nói về ngôn ngữ hƣớng đối tƣợng thì ta gọi một hàm là một phƣơng thức hay hành vi. Tất cả các tên này điều tƣơng đồng với nhau. Một phƣơng thức có thể lấy bất kỳ số lƣợng tham số nào, các tham số này nằm sau tên của phƣơng thức và đƣợc bao bọc bên trong dấu ngoặc tròn (). Mỗi tham số phải khai báo kèm với kiểu dữ liệu. Ví dụ ta có một khai báo định nghĩa một phƣơng thức có tên là Method, phƣơng thức không trả về giá trị nào cả (khai báo giá trị trả về là void) và có hai tham số là một kiểu int và button: void Method( int param1, button param2) { // } Bên trong thân của phƣơng thức, các tham số này đƣợc xem nhƣ những biến cục bộ, giống nhƣ là khai báo biến bên trong phƣơng thức và khởi tạo giá trị bằng giá trị
- của tham số truyền vào. Ví dụ sau minh họa việc truyền tham số vào một phƣơng thức, trong trƣờng hợp này thì hai tham số có kiểu là int và float. Ví dụ: Truyền tham số cho phƣơng thức using System; public class Class1 { public void SomeMethod(int p1, float p2){ Console.WriteLine(“Ham nhan duoc hai tham so:”, p1,p2); } } public class Tester { static void Main(){ int var1 = 5; float var2 = 10.5f; Class1 c = new Class1(); c.SomeMethod( var1, var2 ); } } Phƣơng thức SomeMethod sẽ lấy hai tham số int và float rồi hiển thị ra màn hình bằng việc dùng hàm Console.WriteLine(). Những tham số này có tên là p1 và p2 đƣợc xem nhƣ là biến cục bộ bên trong của phƣơng thức. Trong phƣơng thức gọi Main, có hai biến cục bộ đƣợc tạo ra là var1 và var2. Khi hai biến này đƣợc truyền cho phƣơng thức SomeMethod thì chúng đƣợc ánh xạ thành hai tham số p1 và p2 theo thứ tự danh sách biến đƣa vào. Trong ví dụ trên hai tham số int p1 và float p2 trong hàm SomeMethod(int p1, float p2) còn đƣợc gọi là tham số hình thức, hai tham số var1 và var2 trong lời gọi hàm SomeMethod( var1, var2 ) đƣợc gọi là tham số thực sự. 2.7.2. Tạo đối tƣợng a) Tạo đối tƣợng Những kiểu dữ liệu chuẩn của C# nhƣ int, char, float, là những kiểu dữ liệu giá trị và các biến đƣợc tạo ra từ các kiểu dữ liệu này đƣợc lƣu trên stack. Tuy nhiên, với các đối tƣợng kiểu dữ liệu tham chiếu thì đƣợc tạo ra trên heap, sử dụng từ khóa new để tạo một đối tƣợng: ThoiGian t = new ThoiGian(); Biến t không chứa giá trị của đối tƣợng ThoiGian, nó chỉ chứa địa chỉ của đối tƣợng đƣợc tạo ra trên heap, do vậy t chỉ chứa tham chiếu đến một đối tƣợng mà thôi.
- b) Hủy đối tƣợng Ngôn ngữ C# cung cấp cơ chế thu dọn (garbage collection) và do vậy không cần phải khai báo tƣờng minh các phƣơng thức hủy. Tuy nhiên, để rõ ràng thì cần phải khai báo tƣờng minh các phƣơng thức hủy để giải phóng các tài nguyên. ~Class1() { // Thực hiện một số công việc } 2.8. Xử lý ngoại lệ Ngôn ngữ C# cũng giống nhƣ bất cứ ngôn ngữ hƣớng đối tƣợng khác, cho phép xử lý những lỗi và các điều kiện không bình thƣờng với những ngoại lệ. Ngoại lệ là một đối tƣợng đóng gói những thông tin về sự cố của một chƣơng trình không bình thƣờng. Một điều quan trọng để phân chia giữa bug, lỗi và ngoại lệ. Một bug là một lỗi lập trình có thể đƣợc sửa chữa trƣớc khi mã nguồn đƣợc chuyển giao. Những ngoại lệ thì không đƣợc bảo vệ và tƣơng phản với những bug. Mặc dù một bug có thể là nguyên nhân sinh ra ngoại lệ, cũng không dựa vào những ngoại lệ để xử lý những bug trong chƣơng trình, tốt hơn nên sửa chữa những bug này. Một lỗi có nguyên nhân là do phía hành động của ngƣời sử dụng. Ví dụ, ngƣời sử dụng nhập vào một số nhƣng họ lại nhập vào ký tự chữ cái. Một lần nữa, lỗi có thể làm xuất hiện ngoại lệ, nhƣng có thể ngăn ngừa điều này bằng cách bắt giữ lỗi với mã hợp lệ. Những lỗi có thể đƣợc đoán trƣớc và đƣợc ngăn ngừa. Thậm chí nếu xóa tất cả những bug và dự đoán tất cả các lỗi của ngƣời dùng, cũng có thể gặp phải những vấn đề không mong đợi, nhƣ là xuất hiện trạng thái thiếu bộ nhớ (out of memory), thiếu tài nguyên hệ thống, những nguyên nhân này có thể do các chƣơng trành khác cùng hoạt động ảnh hƣởng đến. Không thể ngăn ngừa các ngoại lệ này, nhƣng có thể xử lý để không thể làm tổn hại đến chƣơng trình. Khi một chƣơng trình gặp một tình huống ngoại lệ, nhƣ là thiếu bộ nhớ thì nó sẽ tạo một ngoại lệ. Khi một ngoại lệ đƣợc tạo ra, việc thực thi của các chức năng hiện hành sẽ bị treo cho đến khi nào việc xử lý ngoại lệ tƣơng ứng đƣợc tìm thấy. Điều này có nghĩa rằng nếu chức năng hoạt động hiện hành không thực hiện việc xử lý ngoại lệ, thì chức năng này sẽ bị chấm dứt và hàm gọi sẽ nhận sự thay đổi đến việc xử lý ngoại lệ. Nếu hàm gọi này không thực hiện việc xử lý ngoại lệ, ngoại lệ sẽ đƣợc xử lý sớm bởi CLR, điều này dẫn đến chƣơng trình sẽ kết thúc. Một trình xử lý ngoại lệ là một khối lệnh chƣơng trình đƣợc thiết kế xử lý các ngoại lệ mà chƣơng trình phát sinh. Xử lý ngoại lệ đƣợc thực thi trong câu lệnh catch.
- Nếu một ngoại lệ đƣợc bắt và đƣợc xử lý, thì chƣơng trình có thể sửa chữa đƣợc vấn đề và tiếp tục thực hiện hoạt động. Nếu chƣơng trình không tiếp tục, bằng việc bắt giữ ngoại lệ để in ra những thông điệp có nghĩa và kết thúc chƣơng trình một cách rõ ràng. Nếu đoạn chƣơng trình thực hiện mà không quan tâm đến bất cứ ngoại lệ có thể gặp (nhƣ khi giải phóng tài nguyên mà chƣơng trình đƣợc cấp phát), có thể đặt đoạn mã này trong khối finally, khi đó nó sẽ chắc chắn đƣợc thực hiện thậm chí ngay cả khi có một ngoại lệ xuất hiện. Trong ngôn ngữ C# chỉ có thể phát sinh (throw) những đối tƣợng của các kiểu dữ liệu là System.Exception, hay những đối tƣợng đƣợc dẫn xuất từ kiểu dữ liệu này. Namespace System của CLR chứa một số các kiểu dữ liệu xử lý ngoại lệ có thể sử dụng trong chƣơng trình. Những kiểu dữ liệu ngoại lệ này bao gồm ArgumentNull-Exception, InValidCastException và OverflowException, cũng nhƣ nhiều lớp khác nữa. 2.8.1. Câu lệnh throw Để cảnh báo sự không bình thƣờng trong một lớp của ngôn ngữ C# phát sinh một ngoại lệ. Để làm đƣợc điều này sử dụng từ khóa throw. Dòng lệnh sau tạo ra một thể hiện mới của System.Exception và sau đó throw nó: throw new System.Exception(); Khi phát sinh ngoại lệ thì ngay tức khắc sẽ làm ngừng việc thực thi trong khi CLR sẽ tìm kiếm một trình xử lý ngoại lệ. Nếu một trình xử lý ngoại lệ không đƣợc tìm thấy trong phƣơng thức hiện thời, thì CLR tiếp tục tìm trong phƣơng thức gọi cho đến khi nào tìm thấy. Nếu CLR trả về lớp Main() mà không tìm thấy bất cứ trình xử lý ngoại lệ nào, thì nó sẽ kết thúc chƣơng trình. Ví dụ: Throw ngoại lệ namespace Programming_CSharp { using System; public class Test { public static void Main(){ Console.WriteLine(“Enter Main ”); Test t = new Test(); t.Func1(); Console.WriteLine(“Exit Main ”); } public void Func1() { Console.WriteLine(“Enter Func1 ”);
- Func2(); Console.WriteLine(“Exit Func1 ”); } public void Func2() { Console.WriteLine(“Enter Func2 ”); throw new System.Exception(); Console.WriteLine(“Exit Func2 ”); } } } Ví dụ này viết ra màn hình console thông tin khi nó nhập vào trong một hàm và chuẩn bị đi ra từ một hàm. Hàm Main() tạo thể hiện mới của kiểu Test và sau đó gọi hàm Func1(). Sau khi in thông điệp “Enter Func1”, hàm Func1() này gọi hàm Func2(). Hàm Func2() in ra thông điệp đầu tiên và phát sinh một ngoại lệ kiểu System.Exception. Việc thực thi sẽ ngƣng ngay tức khắc và CLR sẽ tìm kiếm trình xử lý ngoại lệ trong hàm Func2(). Do không tìm thấy ở đây, CLR tiếp tục vào stack lấy hàm đã gọi trƣớc tức là Func1 và tìm kiếm trình xử lý ngoại lệ. Một lần nữa trong Func1 cũng không có đoạn xử lý ngoại lệ. Và CLR trả về hàm Main. Tại hàm Main cũng không có, nên CLR sẽ gọi trình mặc định xử lý ngoại lệ, việc này đơn giản là xuất ra một thông điệp lỗi. 2.8.2. Câu lệnh catch Trong C#, một trình xử lý ngoại lệ hay một đoạn chƣơng trình xử lý các ngoại lệ đƣợc gọi là một khối catch và đƣợc tạo ra với từ khóa catch. Trong ví dụ sau, câu lệnh throw đƣợc thực thi bên trong khối try và một khối catch đƣợc sử dụng để công bố rằng một lỗi đã đƣợc xử lý. Ví dụ: Bắt giữ ngoại lệ namespace Programming_CSharp { using System; public class Test { public static void Main() { Console.WriteLine(“Enter Main ”); Test t = new Test(); t.Func1();
- Console.WriteLine(“Exit Main ”); } public void Func1() { Console.WriteLine(“Enter Func1 ”); Func2(); Console.WriteLine(“Exit Func1 ”); } public void Func2() { Console.WriteLine(“Enter Func2 ”); try{ Console.WriteLine(“Entering try block ”); throw new System.Exception(); Console.WriteLine(“Exiting try block ”); } catch { Console.WriteLine(“Exception caught and handled.”); } Console.WriteLine(“Exit Func2 ”); } } } Ví dụ Throw ngoại lệ và ví dụ bắt giữ ngoại lệ ở trên tƣơng tự nhau ngoại trừ chƣơng trình trong ví dụ bắt giữ ngoại lệ thêm vào trong một khối try/catch. Thông thƣờng có thể đặt khối try bao quanh những đoạn chƣơng trình tiềm ẩn gây ra sự nguy hiểm, nhƣ là việc truy cập file, cấp phát bộ nhớ Theo sau khối try là câu lệnh catch tổng quát. Câu lệnh catch trong ví dụ này là tổng quát bởi vì không xác định loại ngoại lệ nào bắt giữ. Trong trƣờng hợp tổng quát này thì khối catch này sẽ bắt giữ bất cứ ngoại lệ nào đƣợc phát sinh. Trong ví dụ bắt giữ ngoại lệ, khối catch đơn giản là thông báo ra một ngoại lệ đƣợc bắt giữ và đƣợc xử lý. Trong ví dụ cụ thể có thể đƣa hành động đúng để sửa chữa vấn đề gây ra sự ngoại lệ. Ví dụ, nếu ngƣời sử dụng đang cố mở một tập tin có thuộc tính chỉ đọc, chúng ta có thể gọi một phƣơng thức cho phép ngƣời dùng thay đổi thuộc tính của tập tin. Nếu chƣơng trình thực hiện thiếu bộ nhớ, chúng ta có thể phát sinh cho ngƣời
- dùng cơ hội để đóng bớt các ứng dụng khác lại. Thậm chí trong trƣờng hợp xấu nhất ta không khắc phục đƣợc thì khối catch này có thể in ra thông điệp lỗi để ngƣời dùng biết. Trong ví dụ bắt giữ ngoại lệ, chúng ta thấy xuất hiện đoạn mã đi vào từng hàm nhƣ Main(), Func1(), Func2() và cả khối try. Chúng ta không bao giờ thấy nó thoát khối lệnh try (tức là in ra thông báo “Exiting try block ”, hay thực hiện lệnh này), mặc dù nó vẫn thoát ra theo thứ tự Func2(), Func1() và Main(). Chuyện gì xảy ra? Khi một ngoại lệ đƣợc phát sinh, việc thi hành ngay lập tức sẽ bị tạm dừng và việc thi hành sẽ đƣợc chuyển qua khối lệnh catch. Nó không bao giờ trả về luồng thực hiện ban đầu, tức là các lệnh sau khi phát ra ngoại lệ trong khối try không đƣợc thực hiện. Trong trƣờng hợp này chúng ta sẽ không bao giờ nhận đƣợc thông báo “Exiting try block ”. Khối lệnh catch xử lý lỗi và sau đó chuyển việc thực thi chƣơng trình đến các lệnh tiếp sau khối catch. Ở đây không có việc quay lại cuộc gọi hàm trƣớc trong stack. Ngoại lệ bây giờ đƣợc xử lý, không có vấn đề gì xảy ra và chƣơng trình tiếp tục hoạt động bình thƣờng. Điều này trở nên rõ ràng hơn nếu chúng ta di chuyển khối try/catch lên hàm Func1 nhƣ trong ví dụ bên dƣới. Ví dụ: Catch trong hàm gọi namespace Programming_CSharp { using System; public class Test { public static void Main() { Console.WriteLine(“Enter Main ”); Test t = new Test(); t.Func1(); Console.WriteLine(“Exit Main ”); } public void Func1() { Console.WriteLine(“Enter Func1 ”); try{ Console.WriteLine(“Entering try block ”); Func2(); Console.WriteLine(“Exiting try block ”); }
- catch{ Console.WriteLine(“Exception caught and handled.”); } Console.WriteLine(“Exit Func1 ”); } public void Func2() { Console.WriteLine(“Enter Func2 ”); throw new System.Exception(); Console.WriteLine(“Exit Func2 ”); } } } Lúc này ngoại lệ không đƣợc xử lý bên trong hàm Func2(), mà nó đƣợc xử lý bên trong hàm Func1(). Khi hàm Func2() đƣợc gọi, nó in câu lệnh thông báo vào hàm rồi phát sinh một ngoại lệ. Việc thực hiện chƣơng trình bị ngƣng, CLR tìm kiếm phần xử lý ngoại lệ, nhƣng trong hàm này không có và CLR vào stack lấy hàm gọi trong trƣờng hợp này là Func1(). Câu lệnh catch sẽ đƣợc gọi và việc thực thi tiếp tục thực hiện bình thƣờng sau câu lệnh catch. Chúng ta đã dùng khối catch tổng quát, tức là với bất cứ ngoại lệ nào cũng đƣợc. Tuy nhiên chúng ta có thể tạo ra khối catch xác định để xử lý chỉ một vài các ngoại lệ chứ không phải toàn bộ ngoại lệ, dựa trên kiểu của ngoại lệ phát sinh. Ví dụ sau minh họa cách xác định loại ngoại lệ mà chúng ta xử lý. Ví dụ: Xác định ngoại lệ để bắt namespace Programming_CSharp { using System; public class Test { public static void Main() { Test t = new Test(); t.TestFunc(); } // ta thử chia hai phần xử lý ngoại lệ riêng public void TestFunc() { try{
- double a = 5; double b = 0; Console.WriteLine(“{0} / {1} = {2}”, a, b, DoDivide(a,b)); } catch (System.DivideByZeroException){ Console.WriteLine(“DivideByZeroException caught!”); } catch (System.ArithmeticException){ Console.WriteLine(“ArithmeticException caught!”); } catch{ Console.WriteLine(“Unknown exception caught”); } Trong ví dụ này, phƣơng thức DoDivide() sẽ không cho phép chúng ta chia cho zero bởi một số khác và cũng không cho phép chia số zero. Nó sẽ phát sinh một đối tƣợng của Divide- ByzeroException nếu chúng ta thực hiện chia với zero. Trong toán học việc lấy zero chia cho một số khác là đƣợc phép, nhƣng trong ví dụ minh họa của chúng ta không cho phép thực hiện việc này, nếu thực hiện sẽ phát sinh ra một ngoại lệ ArithmeticException. Khi một ngoại lệ đƣợc phát sinh, CLR sẽ kiểm tra mỗi khối xử lý ngoại lệ theo thứ tự và sẽ lấy khối đầu tiên thích hợp. Khi thực hiện với a=5 và b=7 thì kết quả nhƣ sau: 5 / 7 = 0.7142857142857143 Nhƣ vậy, không có ngoại lệ đƣợc phát sinh. Tuy nhiên, khi chúng ta thay đổi giá trị của a là 0, thì kết quả là: ArithmeticException caught! Ngoại lệ đƣợc phát sinh và CLR sẽ kiểm tra ngoại lệ đầu tiên: DivideByZero Exception. Vì không phù hợp, nên sẽ tiếp tục đi tìm và khối xử lý Arithmetic Exception đƣợc chọn. Giả sử chúng ta thay đổi giá trị của b là 0. Khi thực hiện sẽ dẫn đến ngoại lệ DivideByZeroException. Phải xét kỹ thứ tự của câu lệnh catch, bởi vì DivideByZero-Exception đƣợc dẫn xuất từ ArithmeticException. Nếu chúng ta đảo thứ tự của câu lệnh catch, thì ngoại lệ DivideByZeroException sẽ đƣợc phù hợp với khối xử lý ngoại lệ Arith- meticException. Và việc xử lý ngoại lệ sẽ không bao giờ đƣợc giao cho khối xử lý DivideByZeroException. Thật vậy, nếu thứ tự này đƣợc đảo, nó sẽ không cho phép bất
- cứ ngoại lệ nào đƣợc xử lý bởi khối xử lý ngoại lệ DivideByZeroException. Trình biên dịch sẽ nhận ra rằng DivideByZero Exception không thực hiện bất cứ khi nào và nó sẽ thông báo một lỗi biên dịch. Có thể phân phối câu lệnh try/catch, bằng cách bắt giữ những ngoại lệ xác định trong một hàm và nhiều ngoại lệ tổng quát trong nhiều hàm. Mục đích của thực hiện này là đƣa ra các thiết kế đúng. Giả sử chúng ta có phƣơng thức A, phƣơng thức này gọi một phƣơng thức khác tên là phƣơng thức B, đến lƣợt mình phƣơng thức B gọi phƣơng thức C. Và phƣơng thức C tiếp tục gọi phƣơng thức D, cuối cùng phƣơng thức D gọi phƣơng thức E. Phƣơng thức E ở mức độ sâu nhất trong chƣơng trình của chúng ta, phƣơng thức A, B ở mức độ cao hơn. Nếu chúng ta đoán trƣớc phƣơng thức E có thể phát sinh ra ngoại lệ, chúng ta có thể tạo ra khối try/catch để bắt giữ những ngoại lệ này ở chỗ gần nơi phát sinh ra ngoại lệ nhất. Chúng ta cũng có thể tạo ra nhiều khối xử lý ngoại lệ chung ở trong đoạn chƣơng trình ở mức cao trong trƣờng hợp những ngoại lệ không đoán trƣớc đƣợc. 2.8.3. Câu lệnh finally Trong một số tình huống, việc phát sinh ngoại lệ và unwind stack có thể tạo ra một số vấn đề. Ví dụ nhƣ khi chúng ta mở một tập tin, xác nhận một tài nguyên, chúng ta đóng một tập tin hay là giải phóng bộ nhớ đệm mà chƣơng trình đã chiếm giữ trƣớc đó. Trong ngôn ngữ C#, vấn đề này ít xảy ra hơn do cơ chế thu dọn tự động của C# ngăn ngừa những ngoại lệ phát sinh từ việc thiếu bộ nhớ. Tuy nhiên, có một số hành động mà chúng ta cần phải quan tâm là bất cứ khi nào một ngoại lệ đƣợc phát sinh ra, nhƣ việc đóng một tập tin, chúng ta có hai chiến lƣợc để lựa chọn thực hiện. Một hƣớng tiếp cận là đƣa hành động nguy hiểm vào trong khối try và sau đó thực hiện việc đóng tập tin trong cả hai khối catch và try. Tuy nhiên, điều này gây ra đoạn chƣơng trình không đƣợc đẹp do sử dụng trùng lắp lệnh. Ngôn ngữ C# cung cấp một sự thay thế tốt hơn trong khối finally. Đoạn chƣơng trình bên trong khối catch đƣợc đảm bảo thực thi mà không quan tâm đến việc khi nào thì một ngoại lệ đƣợc phát sinh. Phƣơng thức TestFunc() trong ví dụ sau minh họa việc mở một tập tin nhƣ là hành động đầu tiên của nó, sau đó phƣơng thức thực hiện một vài các phép toán toán học và sau đó là tập tin đƣợc đóng. Có thể trong quá trình mở tập tin cho đến khi đóng tập tin chƣơng trình phát sinh ra một ngoại lệ. Nếu xuất hiện ngoại lệ, khi đó tập tin vẫn còn mở nhƣng cuối của phƣơng thức này tập tin sẽ đƣợc đóng. Do chức năng đóng tập tin đƣợc di chuyển vào trong khối finally, ở đây nó sẽ đƣợc thực thi mà không cần quan tâm đến việc có phát sinh hay không một ngoại lệ trong chƣơng trình.
- Ví dụ: Sử dụng khối finally namespace Programming_CSharp { using System; public class Test { public static void Main() { Test t = new Test(); t.TestFunc(); } public void TestFunc(){ try { Console.WriteLine(“Open file here”); double a = 5; double b = 0; Console.WriteLine(“{0} /{1} = {2}”, a, b, DoDivide(a,b)); Console.WriteLine(“This line may or not print”); } catch (System.DivideByZeroException){ Console.WriteLine(“DivideByZeroException caught!”); } catch{ Console.WriteLine(“Unknown exception caught”); } finally{ Console.WriteLine(“Close file here.”); } } public double DoDivide(double a, double b){ if ( b == 0){ throw new System.DivideByZeroException(); } if ( a == 0){ throw new System.ArithmeticException(); } return a/b; } }}
- Trong ví dụ này một khối catch đƣợc loại bỏ và thêm vào khối finally. Bất cứ khi một ngoại lệ đƣợc phát sinh ra hay không thì khối lệnh trong finally cũng đƣợc thực thi. Do vậy nên trong cả hai trƣờng hợp ta cũng thấy xuất hiện thông điệp “Close file here”. 2.9. Bài tập 1. Cho biết chƣơng trình sau thực hiện điều gì? using System; class variables { public static void Main(){ int radius = 4; const double PI = 3.14159; double circum, area; area = PI * radius* radius; circum = 2 * PI * radius; Console.WriteLine(“Ban kinh = {0}, PI = {1}”, radius, PI); Console.WriteLine(“Dien tich {0}”, area); Console.WriteLine(“Chu vi {0}”, circum); } } 2. Cho biết chƣơng trình sau thực hiện điều gì? class AClass { static void Main(){ int x, y; for( x = 0; x < 10; x++, System.Console.Write(“\n”)); for( y = 0 ; y < 10; y++, System.Console.WriteLine(“{0}”,y)); } } 3. Cho biết chƣơng trình sau thực hiện điều gì? class BaiTap3_1 { public static void Main(){ int x = 0; for(x = 1; x < 10; x++) { System.Console.Write(“{0:03}”, x); } } }
- 4. Tìm và sửa lỗi chƣơng trình sau class Test { pubic static void Main(){ Console.WriteLine(“Xin chao”); Consoile.WriteLine(“Tam biet”); } } 5. Tìm và sửa lỗi chƣơng trình sau class Test { pubic void Main(){ Console.WriteLine(„Xin chao‟); Consoile.WriteLine(„Tam biet‟); } } 6. Tìm và sửa lỗi chƣơng trình sau class BaiTap3_2 { public static void Main(){ for(int i=0; i < 10 ; i++) System.Console.WriteLine(“so :{1}”, i); } } 7. Tìm và sửa lỗi chƣơng trình sau using System; class BaiTap3_3 { public static void Main() { double myDouble; decimal myDecimal; myDouble = 3.14; myDecimal = 3.14; Console.WriteLine(“My Double: {0}”, myDouble); Console.WriteLine(“My Decimal: {0}”, myDecimal); } }
- 8. Tìm và sửa lỗi chương trình sau class BaiTap3_4 { static void Main() { int value; if (value > 100); System.Console.WriteLine(“Number is greater than 100”); } } 9. Viết chƣơng trình hiển thị trên màn hình nhƣ sau 10. Viết chƣơng trình giải phƣơng trình bậc nhất, cho phép ngƣời dùng nhập vào giá trị a, b. 11. Viết chƣơng trình giải phƣơng trình bậc hai, cho phép ngƣời dùng nhập vào giá trị a, b, c. 12. Viết chƣơng trình tính chu vi và diện tích của các hình sau: đƣờng tròn, hình chữ nhật, hình thang, tam giác. 13. Viết chƣơng trình nhập vào số nguyên dƣơng n. In ra màn hình kết quả của tổng sau: S=1+3+5+7+ +n 14. Viết chƣơng trình nhập vào m số nguyên sau đó hiển thị các số đó ra màn hình Hƣớng dẫn: using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 { class Program
- { static void Main(string[] args) { int m,i; int[] a= new int[100]; Console.Write("Nhap so luong phan tu mang:"); m =Convert.ToInt32(Console.ReadLine()); //hoac m = int.Parse(Console.ReadLine()); for (i = 1; i <= m; i++) { Console.Write("Nhap phan tu thu " + i + ":"); a[i]=Convert.ToInt32(Console.ReadLine()); } Console.WriteLine("Cac gia tri vua nhap:"); for (i = 1; i <= m; i++) { Console.WriteLine(a[i]); } Console.ReadLine(); } } } 15. Viết chƣơng trình nhập vào m số nguyên sau đó hiển thị các số đó ra màn hình theo thứ tự tăng dần. 16. Xây dựng lớp sinh viên gồm các thuộc tính: họ tên, địa chỉ, số điện thoại. Nhập thông tin của n sinh viên sau đó hiển thị các thông tin này ra màn hình Hƣớng dẫn: using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication3 { class sv { public string ht, dc; public int dt; }
- class Program { static void Main(string[] args) { sv[] a = new sv[100]; int i, n; Console.WriteLine("Nhap so luong SV:"); n=Convert.ToInt32(Console.ReadLine()); for (i = 0; i < n; i++) { a[i] = new sv(); Console.WriteLine("Nhap thong tin SV thu " + (i + 1)); Console.Write("\t Nhap ho ten:"); a[i].ht = Console.ReadLine(); Console.Write("\t Nhap dia chi:"); a[i].dc = Console.ReadLine(); Console.Write("\t Nhap diem toan:"); a[i].dt = Convert.ToInt32(Console.ReadLine()); } Console.WriteLine("Thong tin sinh vien"); for (i = 0; i < n; i++) { Console.WriteLine(a[i].ht + "\t" + a[i].dc + "\t" + a[i].dt); } Console.ReadLine(); } } } 17. Xây dựng lớp nhân viên gồm các thuốc tính: Mã nhân viên, tên nhân viên, năm sinh, hệ số lƣơng và các phƣơng thức Nhập, Hiển thị. Viết chƣơng trình nhập thông tin của n nhân viên sau đó hiển thị các thông tin này ra màn hình. 18. Chƣơng trình sau đây bị lỗi. Hãy xác định lỗi có thể phát sinh ngoại lệ khi chạy chƣơng trình. Và viết lại chƣơng trình hoàn chỉnh gồm các lệnh xử lý ngoại lệ. using System; public class Tester { public static void Main() { uint so1=0; int so2, so3;
- so2 = -10; so3 = 0; // tính giá trị lại so1 -= 5; so2 = 5/so3; // xuất kết quả Console.WriteLine("So 1: {0}, So 2:{1}", so1, so2); } } 19. Chƣơng trình sau đây có thể dẫn đến ngoại lệ hay không? Nếu có thì hãy cho biết ngoại lệ có thể đƣợc phát sinh. Hãy viết lại chƣơng trình hoàn chỉnh có xử lý các ngoại lệ bằng cách đƣa ra thông điệp về ngoại lệ đƣợc phát sinh. using System; using System.IO; public class Tester { public static void Main() { string fname = "test3.txt"; string buffer; StreamReader sReader = File.OpenText(fname); while ( (buffer = sReader.ReadLine()) !=null) { Console.WriteLine(buffer); } } }
- CHƢƠNG 3: LÀM VIỆC VỚI WEB FORM 3.1. ASP.NET và Web Form 3.1.1. Mô hình lập trình phía máy chủ Trong thế giới Web, tất cả các giao tiếp giữa Client (trình duyệt) và Server (máy chủ Web) đều đƣợc thực hiện theo cơ chế “Request and Response”. Tức là, trƣớc tiên phía máy khách cần phải “Requesst” (gửi yêu cầu) tới Server sau đó phía chủ sẽ “Response” (phúc đáp) lại yêu cầu. Cùng một cơ chế này ngƣời ta có hai cách tiếp cận để xử lý “Request trang Web” từ máy khách. Cách 1: Khi máy khách yêu cầu một trang ví dụ trang Web abc thì máy chủ sẽ đọc toàn bộ nội dung của trang và gửi về cho phía máy khách mà không thực hiện bất kỳ xử lý nào. Nó hoàn toàn không qua tâm đến ý nghĩa bên trong của trang abc. Nội dung trang này sau đó sẽ đƣợc phía trình duyệt xử lý. Mô hình theo cách này gọi là mô hình lập trình phía máy khách. Cách 2: Khi máy khách yêu cầu một trang ví dụ trang Web xyz thì máy chủ sẽ đọc toàn bộ nội dung của trang đó và xử lý tại Server (trƣớc khi gửi về cho client) để đƣợc kết quả, tiếp theo lấy kết quả xử lý đƣợc gửi về cho phía máy khách. Kết quả trả về cho máy khách có thể chứa các phần tử HTML, các câu lệnh JavaScript, các định nghĩa kiểu CSS . và tiếp tục đƣợc phía Client (trình duyệt) xử lý nhƣ cách 1. Với cách 1, do việc xử lý không diễn ra bên phía Server nên trang Web không thể đọc/ghi các dữ liệu trên Server đƣợc (ví dụ danh sách khách hàng, danh mục sản phẩm, ). Vì vậy nó chỉ phù hợp với các trang Web đơn giản không đòi hỏi xử lý chi tiết. Với cách 2, do việc xử lý thông tin ở tại Server nên hoàn toàn có thể đọc/ghi dữ liệu trên chính Server đó. Vì vậy nó phù hợp với các dự án lớn và tính bảo mật cao. Mô hình theo cách này gọi là mô hình lập trình phía máy chủ. Hình 3.1. Mô hình lập trình phía máy khách
- Trong mô hình lập trình ở phía máy khách, máy chủ web chỉ đọc trang và gửi yêu cầu về cho máy khách. Hình 3.2. Mô hình lập trình phía máy chủ Trong mô hình lập trình phía máy chủ trang Web đƣợc xử lý trƣớc tiên bên Web Server sau đó mới gửi về cho máy khách xử lý tiếp. 3.1.2. Giới thiệu về ASP.NET Nhƣ chúng ta đã biết, ASP vẫn còn tồn đọng một số khó khăn nhƣ Code ASP và HTML lẫn lộn, điều này làm cho quá trình viết code khó khăn, thể hiện và trình bày code không trong sáng, hạn chế khả năng sử dụng lại code. Bên cạnh đó, khi triển khai cài đặt, do không đƣợc biên dịch trƣớc nên dễ bị mất source code. Thêm vào đó, ASP không có hỗ trợ cache, không đƣợc biên dịch trƣớc nên phần nào hạn chế về mặt tốc độ thực hiện. Quá trình xử lý Postback khó khăn, Đầu năm 2002, Microsoft giới thiệu một kỹ thuật lập trình Web khá mới mẻ với tên gọi ban đầu là ASP+, tên chính thức sau này là ASP.Net. Với ASP.Net, không những không cần đòi hỏi bạn phải biết các tag HTML, thiết kế Web, mà nó còn hỗ trợ mạnh lập trình hƣớng đối tƣợng trong quá trình xây dựng và phát triển ứng dụng Web. ASP.Net là kỹ thuật lập trình và phát triển ứng dụng Web ở phía Server (Server- side) dựa trên nền tảng của Microsoft .Net Framework. Hầu hết, những ngƣời mới đến với lập trình Web đều bắt đầu tìm hiểu những kỹ thuật ở phía Client (Client-side) nhƣ: HTML, Java Script, CSS (Cascading Style Sheets). Khi Web browser yêu cầu một trang Web (trang Web sử dụng kỹ thuật client-side), Web Server tìm trang Web mà Client yêu cầu, sau đó gởi về cho Client. Client nhận kết quả trả về từ Server và hiển thị lên màn hình.
- ASP.Net sử dụng kỹ thuật lập trình ở phía Server thì hoàn toàn khác, mã lệnh ở phía Server (ví dụ: mã lệnh trong trang ASP) sẽ đƣợc biên dịch và thi hành tại Web Server. Sau khi đƣợc Server đọc, biên dịch và thi hành, kết quả tự động đƣợc chuyển sang HTML/JavaScript/CSS và trả về cho Client. Tất cả các xử lý lệnh ASP.Net đều đƣợc thực hiện tại Server và do đó, gọi là kỹ thuật lập trình ở phía Server. ASP.Net đƣợc Microsoft phát triển qua nhiều phiên bản từ ASP.Net 1.0 , 1.1, 2.0, 3.0, 3.5, 4.0 và gần đây nhất là phiên bản ASP.Net 4.5 chạy trên .Net Framework 4.5 sử dụng môi trƣờng phát triển tích hợp (IDE) Visual Studio.Net. Yêu cầu về xây dựng các ứng dụng thƣơng mại điện tử ngày càng đuợc phát triển và nâng cao. Khi đó ASP không còn đáp ứng đƣợc yêu cầu đặt ra. ASP đƣợc thiết kế riêng biệt và nằm ở tầng phiá trên hệ điều hành Windows và Internet Information Service, do đó các công dụng của nó hết sức rời rạc và giới hạn. ASP.Net đƣa ra một phƣơng pháp phát triển hoàn toàn mới khác so với ASP trƣớc kia và đáp ứng đƣợc các yêu cầu đặt ra. Các ƣu điểm của ASP.Net: - ASP chỉ sử dụng VBScript và JavaScript mà không sử dụng đƣợc các ngôn ngữ mạnh khác : Visual Basic, C++ Trong khi đó ASP.NET cho phép viết nhiều ngôn ngữ : VBScript, JavaScript, C#, Visual Basic.Net, - ASP.Net sử dụng phong cách lập trình mới: Code behide. Tách code (mã lệnh) riêng, giao diện riêng . Dễ đọc, dễ quản lý và bảo trì. - Trong các trang ASP chúng ta phải viết mã để kiểm tra dữ liệu nhập từ ngƣời dùng, ASP.NET hỗ trợ các validation Controls để kiểm tra chúng ta không cần viết mã, - Hỗ trợ phát triển Web đƣợc truy cập trên các thiết bị di động: PocketPC, Smartphone - Hỗ trợ nhiều Web Server Control . - Hỗ trợ thiết kế và xây dựng Master Page lồng nhau. - Hỗ trợ bẫy lỗi (debug) JavaScript. - Cho phép ngƣời dùng thiết lập giao diện trang Web theo sở thích cá nhân sử dụng Theme, Profile, WebPart. - Tăng cƣờng các tính năng bảo mật (security). - Hỗ trợ kỹ thuật truy cập dữ liệu mới LINQ. - Hỗ trợ kỹ thuật xây dụng các ứng dụng đa phƣơng tiện SilverLight. - Hỗ trợ kỹ thuật bất đồng bộ ASP.Net Ajax. - ASP.Net hỗ trợ mạnh mẽ bộ thƣ viện phong phú và đa dạng của .Net Framework, làm việc với XML, Web Service, truy cập cơ sở dữ liệu qua ADO.Net, - ASPX và ASP có thể cùng hoạt động trong một ứng dụng.
- - Kiến trúc lập trình giống ứng dụng trên Windows. - Hỗ trợ quản lý trạng thái của các Control. - Tự động phát sinh mã HTML cho các Server Control tƣơng ứng với từng loại Browser. - Hỗ trợ nhiều cơ chế Cache. - Triển khai cài đặt : Không cần lock, không cần đăng ký DLL, cho phép nhiều hình thức cấu hình ứng dụng. - Hỗ trợ quản lý ứng dụng ở mức toàn cục: global.aspx có nhiều sự kiện hơn, quản lý Session trên nhiều Server, không cần Cookies. - Trang ASP.Net đƣợc biên dịch trƣớc. Thay vì phải đọc và thông dịch mỗi khi trang Web đƣợc yêu cầu, ASP.Net biên dịch những trang Web động thành những tập tin DLL mà Server có thể thi hành nhanh chóng và hiệu quả. Yếu tố này làm gia tăng tốc độ thực thi so với kỹ thuật thông dịch của ASP. 3.1.3. Cơ chế xử lý file ASP.NET phía máy chủ Đối với các trang ASP.NET thì cơ chế xử lý giống nhƣ đã mô tả ở trên, tức là theo mô hình xử lý bên phía Server. Nhƣng có bổ sung thêm tính năng Compile and Cache. Hình 3.3. Mô hình xử lý tệp tin ASP.NET
- a) Cơ chế xử lý - Ngƣời lập trình phải tạo các trang ASPX (giả sử tên trang đó là abc.aspx) và đặt nó vào trong thƣ mục Web của Web Server. - Trình duyệt gửi yêu cầu tới Server với nội dung “yêu cầu gửi trang .aspx”. - Web Server sẽ biên dịch code của trang aspx (bao gồm cả các mã code VB.NET/C# gọi là code behind hay code file) thành class. - Lớp sau khi đƣợc biên dịch sẽ thực thi. - Trả kết quả về cho trình duyệt Hình 3.4. Quá trình biên dịch trang ASP.NET b) Các yêu cầu sử lý phía Server - Yêu cầu xử lý tại phía Server thông qua Runat=“Server”. Hình 3.5. Yêu cầu xử lý phía Server qua runat=“Server”
- - Yêu cầu xử lý bên phía Server thông qua cặp thẻ . Hình 3.6. Yêu cầu xử lý phía Server qua cặp thẻ Ngoài 2 cách trên, còn 2 cách để yêu cầu xử lý trang Web trực tiếp trên Server, đó là: Đặt các câu lệnh ngay trong cặp thẻ Script nhƣng có thuộc tính runat = “Server”. string HoVaTen = "Aptech Center"; public int Tong (int a, int b) { return a + b; } // Hoặc định nghĩa lớp public class Example { public int Tich (int a, int b) { return a * b; } }
- - Yêu cầu xử lý phía Server thông qua Script. Hình 3.7. Yêu cầu xử lý phía Server qua Script - Yêu cầu xử lý bên phía Server bằng cách đặt trong Code file. Hình 3.8. Yêu cầu xử lý phía Server đặt trong Code file
- 3.1.4. Web Form trong ASP.NET Để xây dựng ứng dụng Web, ASP.NET cung cấp sẵn cho các nhà lập trình rất nhiều lớp ngay khi cài đặt .NET Framework. Trong số các lớp này có một lớp đặc biệt quan trọng là Page. Mỗi lớp Page sẽ trình bày một trang tài liệu tƣơng ứng với một window và đƣợc gọi là một Web Form. Web Form là một công nghệ cho phép xây dựng các trang Web trong đó có thể lập trình đƣợc. Các trang này gọi là ASP.NET Web Form Pages hay ngắn gọn là Web Form. Các trang Web xây dựng bằng ASP.NET sẽ không phụ thuộc vào trình duyệt (tức là trình duyệt nào cũng cho kết quả nhƣ nhau và hiển thị giống nhau). Một số ƣu điểm của Web Forms: - Web Forms có thể đƣợc thiết kế và lập trình thông qua các công cụ phát triển ứng dụng nhanh (RAD). - Web Form hỗ trợ một tập các điều khiển (Controls) có thể mở rộng. - Bất kỳ một ngôn ngữ .NET nào cũng có thể dùng để lập trình với Web Forms. - ASP.NET sử dụng trình thực thi ngôn ngữ chung (CLR) của .NET Framework do đó thừa hƣởng mọi ƣu thế của .NET Framework nhƣ khả năng thừa kế 3.1.5. Tìm hiểu cấu trúc trang ASP.NET Một trang ASP.NET bao gồm cả phần giao diện ngƣời dùng và phần xử lý logic bên trong. Giao diện ngƣời dùng chịu trách nhiệm hiển thị các thông tin và tiếp nhận dữ liệu từ ngƣời dùng trong khi đó phần xử lý (lập trình) đảm nhiệm việc điều khiển sự tƣơng tác của ngƣời dùng với trang Web. Phần giao diện ngƣời dùng bao gồm một file chứa ngôn ngữ đánh dấu nhƣ HTML hoặc XML và Server Controls file này đƣợc gọi là một trang (Page) và có phần mở rộng là aspx. Phần đáp ứng các tƣơng tác của ngƣời dùng với trang Web đƣợc thực hiện bởi một ngôn ngữ lập trình chẳng hạn nhƣ VB.NET và C#, ta có thể thực hiện việc viết code (mã lệnh) bằng bất kỳ ngôn ngữ lập trình nào đƣợc hỗ trợ bởi CLR ở ngay trong trang ASPX hoặc tách ra một file riêng. File tách riêng này đƣợc gọi là file Code Behind hay mới đây gọi là Code file. Đuôi mở rộng của Code file là .vb (nếu dùng ngôn ngữ VB.NET) hoặc .cs (nếu dùng ngôn ngữ C#). Cách lƣu trữ này đƣợc minh họa qua một ứng dụng cụ thể dƣới đây. Trong đó, trang Web thứ nhất Default2.aspx chứa cả code (C#) và giao diện (HTML) còn trang Web thứ hai đặt code và giao diện ra 2 file riêng biệt là Default.aspx và Default.cs. Ta có thể kết hợp để vừa đặt code trong file aspx vừa đặt code trong file cs.
- Hình 3.9. Lƣu trữ mã lệnh trong trang aspx Một Web Form bao gồm hai thành phần. - Thành phần giao diện (trang thisfile.aspx) - Thành phần xử lý (lập trình) thisfile.cs Phân tích một trang ASP.NET trang này lƣu code và giao diện trên hai file. File giao diện Default.aspx public int Hieu (int a, int b) { return a - b; } File mã lệnh Default.cs public partial class Lession03_default : System.Web.UI.Page{ protected void Tong (object sender, EventArgs e) { txtKetQua.Text = (int.Parse (txtA.Text) + int.Parse (txtB.Text)).ToString (); } }
- Trong file Default.aspx: - Page Language="C#" : chỉ ra rằng ngôn ngữ đƣợc sử dụng để lập trình là C# - CodeFile="~/Lession 03/Default.aspx.cs": Cho biết nội dung file chứa code xử lý là file ~/Lession 03/Default.aspx.cs. - Inherits ="Lession03_default": Cho biết là trang giao diện thừa kế từ lớp nào trong file ~/Lession 03/Default.aspx.cs (vì một file có thể có chứa nhiều lớp). - Server side - example 3 Cho biết là thẻ này cần đƣợc xử lý bên phía Server. Tuy nhiên nội dung trong thẻ này không có gì đặc biệt để xử lý và kết quả sau xử lý sẽ là (không có runat=“Server”). - : Cho biết là nội dung trong cặp thẻ Form cần đƣợc xử lý bên phía Server. - : là thẻ tạo ra phần tử textbox, tuy nhiên do có thuộc tính runat = “Server” nên việc tạo này sẽ đƣợc thực hiện ở bên Server, đƣợc kết quả trả về (là - public int Hieu (int a, int b) { return a - b; } Đoạn script này có thuộc tính runat= “Server”, vì vậy nó sẽ đƣợc xử lý phía Server. Thuộc tính language = “C#” cho biết ngôn ngữ sử dụng để viết là C#. Trong file default.cs: Nội dung file này hoàn toàn chứa các câu lệnh của ngôn ngữ lập trình VB.NET hoặc C#. Việc viết code cho file đó hoàn toàn giống nhƣ viết các chƣơng trình trên Window Form hay chƣơng trình Console. Trong file này không đƣợc chứa trực tiếp các thẻ HTML. Các câu lệnh trong file này hoàn toàn đƣợc phép truy cập tới các phần tử ở trong file default.aspx có thuộc tính runat = “Server”. 3.1.6. Các phƣơng pháp viết mã trong ASP.NET Để viết mã (code) phía Server trong trang ASP.NET ta có thể khai báo và sử dụng trực tiếp trong trang ASP.NET, trong file code behind, hoặc từ một thành phần thƣ viện và ta gọi vào. a) Viết code (VB.NET hoặc C#) trong file .aspx
- Phần mã ASP.NET và mã HTML đƣợc viết trong cùng một trang, mã ASP.NET đƣợc viết ở phần . hoặc nằm trong trang ASP.NET nhƣng không trộn lẫn với mã HTML dành cho phần nội dung. dùng thể khai báo biến hoặc viết các hàm, lớp. dùng để gọi giá trị của biến hay của 1 hàm. lấy giá trị dùng trong trang có các đối tượng ràng buộc dữ liệu. Ví dụ: Trang basic.aspx Biến abc vừa khai báo có giá trị b) Viết code trong trang code behind Các file chứa mã code đƣợc gọi là code file hay code behind. Mã lệnh tại đây thƣờng xử lý các tác vụ liên quan đến nghiệp vụ, trong đó cũng có các câu lệnh cho phép gửi kết quả về cho phía trình duyệt. Vì trang ASP.NET kế thừa từ trang aspx.cs nên trong trang .aspx muốn gọi dữ liệu từ biến hay hàm trong file .aspx.cs phải khai báo bổ ngữ truy cập protected hoặc public. Ví dụ: Trang codebehind.aspx Gán giá trị: Lấy giá trị từ code behind Trang codebehind.aspx.cs using System; public partial class codebehind : System.Web.UI.Page { protected string _hello; protected void Page_Load(object sender, EventArgs e) {
- _hello = "Hello World"; lblhello.Text = _hello; } } Trong ví dụ trên có sử dụng một điều khiển ASP.NET là Label nó là một điều khiển để hiển thị dữ liệu. Trong phần code behind có khai báo một biến _hello kiểu string và bổ ngữ truy cập là protected trong sự kiện Page_Load (khi trang đƣợc tải lên) gán _hello = "Hello World" sau đó gán giá trị cho Label bằng giá trị của _hello. Còn trong trang .aspx có sử dùng thẻ để lấy giá trị của _hello để in ra màn hình. Ngƣời ta thƣờng chia các Web Form thành hai phần là trang chứa giao diện (aspx) và trang chứa mã code (.vb; .cs) để đảm bảo tính chuyên môn hóa và dễ bảo trì. 3.1.7. ASP.NET Server Control Để giúp cho việc phát triển các ứng dụng Web nhanh chóng và thuận tiện, ASP.NET cung cấp một tập hợp các điều khiển sẵn có để thực hiện hầu hết các công việc phổ biến hàng ngày. Các điều khiển này chia làm hai loại: HTML Server Control và ASP.NET Server Control. Các điều khiển này đều đƣợc xử lý bên phía Server (có thuộc tính runat=Server) vì vậy đều có thể truy cập đến các phần tử này bằng các câu lệnh C# (các câu lệnh nằm bên trong Code file). Điểm khác biệt giữa HTML Server Control và ASP.NET Server Control ở chỗ. - Điều khiển HTML Server Control thì có số lƣợng và cách thức tạo giống các phần tử HTML mà ta vẫn tạo trong trang HTML, chỉ khác một điều là có thêm runat= “Server” - Điều khiển ASP.NET Control thì có nhiều thuộc tính hơn thực hiện đƣợc chức năng phức tạp hơn HTML Server Controls. a) HTML Server Control Điều khiển HTML (tag HTML) trong trang ASP.NET có thể xem nhƣ những chuỗi văn bản bình thƣờng. Để có thể đƣợc sử dụng lập trình ở phía Server ta gán thuộc tính runat="Server" cho các điều khiển HTML đó. Những điều khiển HTML (tag HTML) có thuộc tính runat="Server" đƣợc gọi là HTML Server Control. Các đối tƣợng thẻ HTML Server Controls khai báo trong namespace System.Web.UI.HtmlControls đƣợc lấy từ lớp cơ sở HtmlControl. Cú pháp tạo phần tử HTML Server Control: Trong đó: Tên loại thẻ là input, select, p, h1, .
- Ví dụ: HTML Server Control Hình 3.10. Các HTML Server Controls HTML Server Controls bao gồm hai nhóm chính thuộc lớp HtmlControl là: HTMLInputControl, HTMLContainerControl và ba điều khiển phụ là HTMLImage, HTMLLink và HTMLTitle theo mô hình cấu trúc phân cấp sau : Hình 3.11. Cấu trúc lớp HTMLControl
- Các thuộc tính chính trong khai báo các thẻ HTML Control trên dựa theo bảng sau : Điều khiển Thuộc tính chính HtmlAnchor Href, Target, Title HtmlImage, Src, Alt, Width, Height HtmlInputImage HtmlInputCheckBox, Check HtmlInputRadiaButton HtmlInputText Value HtmlInputSelect Items (collection) HtmlTextArea Value HtmlGenericControl InnerText Các sự kiện chính của các thẻ HTMLControl chia theo bảng sau : Sự kiện Điều khiển ServerClick HtmlAnchor, HtmlButton, HtmlInputButton, HtmlInputImage, HtmlInputReset ServerChange HtmlInputText, HtmlInputCheckBox, HtmlInputRadiaButton HtmlInputHidden, HtmlSelect, HtmlTextArea - HtmlAnchor HtmlAchor Control đƣợc sử dụng tƣơng tự nhƣ một thẻ HTML . Trong HTML thẻ đƣợc sử dụng để tạo một Hyperlink, Hyperlink này có thể link tới một bookmark hoặc tới một trang Web khác. Các thuộc tính : Thuộc tính Mô tả Attributes Trả về tất cả tên thuộc tính và giá trị tƣơng ứng của thẻ. Disabled Giá trị boolean xác định Control không/có hiển thị (disabled) trên trang hay không. Mặc định là false. Href Địa chỉ URL của liên kết (link). innerHtml Id duy nhất của Control. innerText Điền vào hay trả về nội dung giữa thẻ đóng và thẻ mở, những kí tự đặc biệt thì không tự động chuyển thành các thực thể (entities). Name Tên của thẻ. OnServerClick Tên hàm đƣợc thực thi khi link đƣợc click. Runat Xác định rằng Control này là Server Control. Phải đƣợc xác
- định là “Server”. Style Xác định hay trả về thuộc tính CSS đƣợc áp dụng cho Control. TagName Trả về tên của thẻ. Target Xác định cửa sổ sẽ đƣợc mở. Title Tựa sẽ đƣợc hiển thị. Visible Giá trị boolean xác định Control sẽ đƣợc hiển thị hay không. Ví dụ: Trang aspx nhƣ sau: Code xử lý phía Server nhƣ sau: public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { link2.HRef = " "; link2.Target = "_blank"; } } Link1 gán thuộc tính href đƣợc gán trực tiếp trong thẻ còn link2 gán href khi trang đƣợc tải lên ở mã lệnh phía Server. Hình 3.12. Minh họa sử dụng điều khiển HtmlAnchor
- - HtmlButton HtmlButton đƣợc sử dụng tƣơng ứng với thẻ HTML . Trong HTML, thẻ đƣợc sử dụng để tạo một nút bấm. Các thuộc tính : Thuộc tính Mô tả Attributes Trả về tất cả tên thuộc tính và giá trị tƣơng ứng của thẻ. Disabled Giá trị boolean xác định Control không/có hiển thị (disabled) trên trang hay không. Mặc định là false. Id Id duy nhất của Control. innerHtml Điền vào hay trả về nội dung giữa thẻ đóng và thẻ mở, những kí tự đặc biệt thì không tự động chuyển thành các entities. innerText Điền vào hay trả về nội dung giữa thẻ đóng và thẻ mở. Những kí tự đặc biệt tự động chuyển thành các entities. OnServerClick Tên hàm đƣợc thực thi khi link đƣợc click. Runat Xác định rằng Control này là Server Control. Phải đƣợc xác định là “Server”. Style Xác định hay trả về thuộc tính CSS đƣợc áp dụng cho Control. TagName Trả về tên của thẻ. Visible Giá trị boolean xác định Control sẽ đƣợc hiển thị hay không. Ví dụ: Trang aspx nhƣ sau : Blue button! Pink button! Code xử lý phía Server nhƣ sau : public partial class _Default : System.Web.UI.Page { protected void b1_Click(object sender, EventArgs e) { p1.InnerHtml = "Bạn đã click vào button màu xanh!"; }
- protected void b2_Click(object sender, EventArgs e) { p1.InnerHtml = "Bạn đã click vào button màu hồng!"; } } Giao diện có hai button một button màu xanh và một button màu hồng. Khi click vào button thì hàm xử lý sự kiện tƣơng ứng sẽ gán nội dung vào thẻ p và hiển lên giao diện nhƣ hình dƣới đây : Hình 3.13. Minh họa sử dụng điều khiển HtmlButton - HtmlForm HtmlForm Control đƣợc sử dụng tƣơng ứng thẻ HTML . Trong HTML, thẻ đƣợc sử dụng để tạo một Form. Các thuộc tính : Thuộc tính Mô tả Action URL nơi mà dữ liệu đƣợc gửi đến khi Form đƣợc submit Attributes Trả về tất cả tên thuộc tính và giá trị tƣơng ứng của thẻ. Disabled Giá trị boolean xác định Control không/có hiển thị (disabled) trên trang hay không. Mặc định là false. Id Id duy nhất của Control. innerHtml Điền vào hay trả về nội dung giữa thẻ đóng và thẻ mở, những kí tự đặc biệt thì không tự động chuyển thành các entities. innerText Điền vào hay trả về nội dung giữa thẻ đóng và thẻ mở. Những kí tự đặc biệt tự động chuyển thành các entities. Method Xác định cách post dữ liệu lên Server. Có 2 giá trị là “post” và “get”. Mặc định là “post” Name Tên của Form Runat Xác định rằng Control này là Server Control. Phải đƣợc xác
- định là “Server”. Style Xác định hay trả về thuộc tính CSS đƣợc áp dụng cho Control. TagName Trả về tên của thẻ. Target Cửa sổ để load URL Visible Giá trị boolean xác định Control sẽ đƣợc hiển thị hay không. Ví dụ: Trang aspx nhƣ sau: Nhập tên của bạn: Code xử lý phía Server nhƣ sau : public partial class _Default : System.Web.UI.Page { protected void submit_Click(object sender, EventArgs e) { p1.InnerHtml = "Chào bạn " + name.Value + "!"; } } Giao diện có một TextBox và một button. Khi click vào Button Submit thì hàm xử lý sự kiện Submit_Click đƣợc thực hiển và ghi ra trang Web: “chào bạn” cùng với tên đƣợc nhập vào textbox nhƣ hình dƣới đây: Hình 3.14. Minh họa sử dụng điều khiển HtmlForm
- - HtmlGeneric HtmlGeneric Control đƣợc dùng để điều khiển thẻ HTML khác chƣa đƣợc chỉ rõ bởi một HTML Server Control đặc biệt, nhƣ , , , , Các thuộc tính : Thuộc tính Mô tả Attributes Trả về tất cả tên thuộc tính và giá trị tƣơng ứng của thẻ. Disabled Giá trị boolean xác định Control không/có hiển thị (disabled) trên trang hay không. Mặc định là false. Id Id duy nhất của Control. innerHtml Điền vào hay trả về nội dung giữa thẻ đóng và thẻ mở, những kí tự đặc biệt thì không tự động chuyển thành các entities. innerText Điền vào hay trả về nội dung giữa thẻ đóng và thẻ mở. Những kí tự đặc biệt tự động chuyển thành các entities. Method Xác định cách post dữ liệu lên Server. Có 2 giá trị là “post” và “get”. Mặc định là “post” Runat Xác định rằng Control này là Server Control. Phải đƣợc xác định là “Server”. Style Xác định hay trả về thuộc tính CSS đƣợc áp dụng cho Control. TagName Trả về tên của thẻ. Visible Giá trị boolean xác định Control sẽ đƣợc hiển thị hay không. - HtmlImage. HtmlImage Control đƣợc sử dụng tƣơng ứng thẻ . Trong HTML, thẻ đƣợc sử dụng để hiển thị hình ảnh. Các thuộc tính : Thuộc tính Mô tả Align Xác định vị trí của hình: Top, Middle, Bottom, Left, Right Alt Mô tả ngắn về hình Attributes Trả về tất cả tên thuộc tính và giá trị tƣơng ứng của thuộc thẻ Border Độ dày của viền xung quanh hình Disabled Giá trị boolean xác định Control có bị disabled hay không. Mặc định là false Height Chiều cao của hình Id Id duy nhất của Control Runat Xác định rằng Control này là Server Control. Phải đƣợc xác
- định là “Server” Src Địa chỉ URL của hình đƣợc hiển thị Style Xác định hay trả về thuộc tính CSS đƣợc áp dụng cho Control TagName Trả về tên của thẻ Visible Giá trị boolean xác định Control sẽ đƣợc hiển thị hay không. Width Chiều rộng của hình Ví dụ: Trang aspx nhƣ sau: Mặt cười Giận dữ Code xử lý phía Server nhƣ sau : public partial class _Default : System.Web.UI.Page { protected void choose_image(object sender, EventArgs e) { image1.Src = select1.Value; } } Giao diện có ComboBox, Button. Khi chọn một lựa chọn trên ComboBox và Click và Button hiển thị thì hình ảnh hiển thị lên sẽ thay đổi tƣơng ứng nhƣ hình dƣới đây: Hình 3.15. Minh họa sử dụng điều khiển HtmlForm
- - HtmlInputButton HtmlInputButton Control đƣợc sử dụng để điều khiển các thẻ , và . Trong HTML những thẻ này đƣợc sử dụng để tạo một nút lệnh, một submit button và một reset button. Các thuộc tính : Thuộc tính Mô tả Attributes Trả về tất cả tên thuộc tính và giá trị tƣơng ứng của thuộc thẻ Disabled Giá trị boolean xác định Control có bị disabled hay không. Mặc định là false Name Tên của thẻ Runat Xác định Control là Server Control. Phải đƣợc xác định là “Server” Style Xác định hay trả về thuộc tính CSS đƣợc áp dụng cho Control TagName Trả về tên của thẻ Type Loại thẻ Value Giá trị của thẻ Visible Giá trị boolean xác định Control sẽ đƣợc hiển thị hay không. - HtmlInputCheckBox HtmlInputCheckBox Control đƣợc sử dụng để điều khiển thẻ . Trong HTML, thẻ này đƣợc sử dụng để tạo một checkbox. Các thuộc tính: Thuộc tính Mô tả Attributes Trả về tất cả tên thuộc tính và giá trị tƣơng ứng của thuộc thẻ Checked Giá trị boolean xác định thẻ có đƣợc chọn hay không. Disabled Giá trị boolean xác định Control có bị disabled hay không. Mặc định là false Id Id duy nhất của Control Name Tên của thẻ Runat Xác định Control là Server Control. Phải đƣợc xác định là “Server” Style Xác định hay trả về thuộc tính CSS đƣợc áp dụng cho Control TagName Trả về tên của thẻ Type Loại thẻ Value Giá trị của thẻ Visible Giá trị boolean xác định Control sẽ đƣợc hiển thị hay không.
- Ví dụ: Trang aspx nhƣ sau: Bạn thích những màu nào? Đỏ Xanh dương Xanh lục Code xử lý phía Server nhƣ sau : public partial class _Default : System.Web.UI.Page { protected void submit(object sender, EventArgs e) { string sResult =""; if (red.Checked) sResult = "đỏ, "; if (green.Checked) sResult = sResult + "xanh lục, "; if (blue.Checked) sResult = sResult + "xanh dương"; p1.InnerHtml = "Bạn thích màu: " + sResult; red.Checked = false; green.Checked = false; blue.Checked = false; } } Giao diện có 3 checkbox và một button. Khi button đƣợc click thì hàm xử lý sự kiện button click đƣợc thực hiển và kiểm tra checkbox nào đƣợc chọn và hiển thị nội dung tƣơng ứng lên. Hình 3.16. Minh họa sử dụng điều khiển HtmlForm
- - HtmlInputFile HtmlInputFile Control đƣợc sử dụng để điều khiển thẻ . Trong HTML, thẻ này đƣợc sử dụng để upload một file lên Server. Các thuộc tính : Thuộc tính Mô tả Accept Danh sách những loại MIME đƣợc chấp nhận Attributes Trả về tất cả tên thuộc tính và giá trị tƣơng ứng của thuộc thẻ Checked Giá trị boolean xác định thẻ có đƣợc chọn hay không. Disabled Giá trị boolean xác định Control có bị disabled hay không. Mặc định là false Id Id duy nhất của Control MaxLength Số kí tự tối đa đƣợc cho phép trong thẻ này Name Tên của thẻ PostedFile Xác định xem có truy xuất đƣợc tới file đƣợc post lên không Runat Xác định rằng Control này là Server Control. Phải đƣợc xác định là “Server” Size Chiều rộng của thẻ Style Xác định hay trả về thuộc tính CSS đƣợc áp dụng cho Control TagName Trả về tên của thẻ Type Loại thẻ Value Giá trị của thẻ Visible Giá trị boolean xác định Control sẽ đƣợc hiển thị hay không. Ví dụ: Trang aspx nhƣ sau : Chọn file để upload lên Server: Tên file: ContentLength: bytes
- Code xử lý phía Server nhƣ sau : public partial class _Default : System.Web.UI.Page { protected void submit(object sender, EventArgs e) { fname.InnerHtml = MyFile.PostedFile.FileName; clength.InnerHtml = MyFile.PostedFile.ContentLength.ToString(); MyFile.PostedFile.SaveAs("c:\\" + MyFile.PostedFile.FileName); } } Giao diện có một HtmlInputFile Control, một HtmlButton Control. Khi chọn file để upload lên Server và nhấn submit thì hàm xử lý sự kiện click của button sẽ đƣợc thực hiển và sẽ lấy tên và độ lớn của file hiển thị lên trang Web nhƣ hình dƣới đây. Hình 3.17. Minh họa sử dụng điều khiển HtmlInputFile - HtmlInputHidden HtmlInputHidden Control đƣợc sử dụng để điều khiển thẻ . Trong HTML, thẻ này đƣợc sử dụng để tạo một hidden input field. Các thuộc tính và sự kiện : Thuộc tính Mô tả Attributes Trả về tất cả tên thuộc tính và giá trị tƣơng ứng của thuộc thẻ Disabled Giá trị boolean xác định Control có bị disabled hay không. Mặc định là false Id Id duy nhất của Control Name Tên của thẻ PostedFile Xác định xem có truy xuất đƣợc tới file đƣợc post lên không