Cộng đồng chia sẻ tri thức Lib24.vn

Bài giảng môn lập trình Windows 1

0ea514e97912fca6af0d80262db69603
Gửi bởi: Khoa CNTT - HCEM 10 tháng 9 2020 lúc 9:50:34 | Được cập nhật: 6 tháng 5 lúc 4:58:31 Kiểu file: PDF | Lượt xem: 274 | Lượt Download: 4 | File size: 1.338611 Mb

Nội dung tài liệu

Tải xuống
Link tài liệu:
Tải xuống

Các tài liệu liên quan


Có thể bạn quan tâm


Thông tin tài liệu

Bài giảng môn lập trình windows 1 MỤC LỤC BÀI 1: MICROSOFT.NET ................................................................................................. 4 1.1 Microsoft.NET ............................................................................................................. 4 1.1.1 Tổng quan ............................................................................................................. 4 1.1.2 Giới thiệu về Visual Studio.NET.......................................................................... 4 1.2 Biên dịch và MSIL ...................................................................................................... 5 1.3 Ngôn ngữ C# ............................................................................................................... 6 BÀI 2: NGÔN NGỮ C# ....................................................................................................... 7 2.1 Tại sao phải sử dụng ngôn ngữ C# .............................................................................. 7 2.3 Các bước chuẩn bị cho chương trình ........................................................................... 8 2.4 Chương trình C# đơn giản ........................................................................................... 8 2.5 Bài tập ........................................................................................................................ 11 CHƢƠNG 3: CƠ BẢN VỀ C# .......................................................................................... 13 3.1 Kiểu dữ liệu ............................................................................................................... 13 3.2 Biến và hằng .............................................................................................................. 16 3.2.1 Biến..................................................................................................................... 16 3.2.2 Hằng ................................................................................................................... 16 3.3 Định danh (tên) .......................................................................................................... 16 3.4 Biểu thức.................................................................................................................... 16 3.5 Khoảng trắng ............................................................................................................. 17 3.6 Toán tử ....................................................................................................................... 17 3.7 Nhập xuất dữ liệu ...................................................................................................... 21 3.7.1 Xuất dữ liệu ra màn hình .................................................................................... 21 3.7.2 Nhập dữ liệu từ bàn phím ................................................................................... 21 3.7.3 Ví dụ ................................................................................................................... 22 3.8 Câu lệnh (statement) .................................................................................................. 23 3.8.1 Cấu trúc điều kiện ............................................................................................... 23 3.8.2 Cấu trúc lựa chọn switch… case ........................................................................ 25 3.8.3 Cấu trúc lặp for ................................................................................................... 28 3.8.4 Vòng lặp không xác định while .......................................................................... 31 3.8.5 Vòng lặp không xác định do … while ................................................................ 32 3.9 Namespace ................................................................................................................. 33 CHƢƠNG 4: PHƢƠNG THỨC ....................................................................................... 35 4.1 Khai báo phương thức ............................................................................................... 35 4.2 Phương thức trả về giá trị .......................................................................................... 35 4.3 Phương thức kiểu void............................................................................................... 36 4.4 Phạm vi của biến ....................................................................................................... 36 4.5 Một vài phương thức toán học thường dùng trong lớp Math .................................... 36 4.6 Ví dụ minh họa .......................................................................................................... 37 4.7 Truyền đối số kiểu tham chiếu có từ khóa ref hoặc out ............................................ 38 4.8 Bài tập ........................................................................................................................ 42 CHƢƠNG 5: XÂY DỰNG LỚP – ĐỐI TƢỢNG ........................................................... 43 5.1 Lớp và đối tượng ....................................................................................................... 43 5.1.1 Định nghĩa lớp .................................................................................................... 43 5.1.2 Thuộc tính truy cập ............................................................................................. 44 5.1.3 Tạo đối tượng ..................................................................................................... 45 5.1.4 Sử dụng đối tượng .............................................................................................. 45 5.2 Phương thức khởi tạo (Constructor) .......................................................................... 46 5.3 Hủy đối tượng ............................................................................................................ 48 5.3.1 Bộ hủy của C# .................................................................................................... 48 Tr n o n n n N – M – u – N 1 Bài giảng môn lập trình windows 1 5.4 Nạp chồng phương thức ............................................................................................ 48 5.5 Đóng gói dữ liệu với thành phần thuộc tính .............................................................. 49 5.5.1 Truy cập lấy dữ liệu (get accessor) ..................................................................... 51 5.5.2 Bộ truy cập thiết lập dữ liệu (set accessor) ......................................................... 51 CHƢƠNG 6: MẢNG, CHỈ MỤC ..................................................................................... 52 6.1 Mảng một chiều ......................................................................................................... 52 6.1.1 Khai báo mảng: ................................................................................................... 52 6.1.2 Truy cập các thành phần trong mảng ................................................................. 53 6.1.3 Khởi tạo các thành phần của mảng ..................................................................... 54 6.1.4 Câu lệnh lặp foreach ........................................................................................... 54 6.1.5 Sử dụng từ khóa params ..................................................................................... 55 6.2 Mảng đối tượng ......................................................................................................... 56 6.3 Mảng đa chiều ( 2 chiều) ........................................................................................... 57 6.4 Bộ chỉ mục ................................................................................................................. 58 6.5 Bài tập ........................................................................................................................ 61 CHƢƠNG 7: KẾ THỪA – ĐA HÌNH ............................................................................. 63 7.1 Đặc biệt hóa và tổng quát hóa ................................................................................... 63 7.2 Sự kế thừa .................................................................................................................. 63 7.3 Đa hình ...................................................................................................................... 66 7.4 Lớp trừu tượng........................................................................................................... 68 7.5 Các lớp lồng nhau ...................................................................................................... 69 CHƢƠNG 8: NẠP CHỒNG TOÁN TỬ .......................................................................... 70 8.1 Sử dụng từ khóa operator .......................................................................................... 70 8.2 Sử dụng toán tử .......................................................................................................... 71 8.3 Toán tử so sánh bằng ................................................................................................. 72 8.4 Toán tử chuyển đổi .................................................................................................... 73 8.5 Bài tập ........................................................................................................................ 74 CHƢƠNG 9: THỰC THI GIAO DIỆN ........................................................................... 75 9.1 Thực thi giao diện ...................................................................................................... 75 9.2 Truy cập phương thức giao diện ................................................................................ 79 9.3 Thực thi phủ quyết giao diện ..................................................................................... 83 9.4 Thực thi giao diện tường minh .................................................................................. 83 9.5 Bài tập ........................................................................................................................ 84 CHƢƠNG 10: XỬ LÝ CHUỖI ........................................................................................ 85 10.1 Lớp string ................................................................................................................ 85 10.2 Tạo một chuỗi .......................................................................................................... 85 10.3 Tạo chuỗi bằng phương thức ToString() ................................................................. 85 10.4 Thao tác trên chuỗi .................................................................................................. 86 10.5 Các biểu thức quy tắt ............................................................................................... 88 10.6 Bài tập ...................................................................................................................... 90 CHƢƠNG 11: CƠ CHẾ ỦY QUYỀN – SỰ KIỆN ......................................................... 91 11.1 Cơ chế ủy quyền ...................................................................................................... 91 11.2 Các sự kiện .............................................................................................................. 92 11.3 Bài tập ...................................................................................................................... 95 CHƢƠNG 12: CÁC LỚP CƠ SỞ .NET .......................................................................... 96 12.1 Lớp đối tượng trong .NET ....................................................................................... 96 12.2 Các lớp cơ sở ........................................................................................................... 97 12.2.1. Lớp Timer ........................................................................................................ 97 12.2.2 Lớp Math .......................................................................................................... 99 12.2.3 Lớp thao tác tập tin ......................................................................................... 101 12.3 Bài tập .................................................................................................................... 106 Tr n o n n n N – M – u – N 2 Bài giảng môn lập trình windows 1 TÀI LIỆU THAM KHẢO............................................................................................... 107 Tr n o n n n N – M – u – N 3 Bài giảng môn lập trình windows 1 BÀI 1: MICROSOFT.NET 1.1 Microsoft.NET 1.1.1 Tổng quan Microsoft.Net gồm 2 phần chính: Framework (khung cảnh) và IDE( Intergrated Development Environment – Môi trường phát triển tích hợp). Framework cung cấp những thứ cần thiết và căn bản, còn IDE cung cấp một môi trường giúp ta triển khai dễ dàng và nhanh chóng những ứng dụng trên nền tảng .NET. Nếu không có IDE chúng ta cũng có thể dùng một trình soạn thảo như Nodepad hay bất kỳ trình soạn thảo văn bản nào và sử dụng command line để biên dịch và thực thi, tuy nhiên việc sử dụng các trình soạn thảo tương đối mất nhiều thời gian. Cách tốt nhất và hiệu quả nhất là sử dụng IDE để phát triển ứng dụng. Microsoft.NET là nền tảng cho việc xây dựng và thực thi các ứng dụng phân tán thế hệ kế tiếp. Bao gồm các ứng dụng từ client đến server và các dịch vụ khác. Một số tính năng của Microsoft.Net cho phép nhà phát triển sử dụng như sau: o Một mô hình lập trình cho phép nhà phát triển xây dựng các ứng dụng dịch vụ web và ứng dụng client với XML. o Tập hợp dịch vụ XML web cho phép nhà phát triển đơn giản và tích hợp người dùng kinh nghiệm o Cung cấp các server phục vụ bao gồm: Windows 2000, SQL Server,… o Các phần mềm client như Windows XP giúp người phát triển phân phối sâu và thuyết phục người dùng thông qua các dòng thiết bị. o Nhiều công cụ hỗ trợ như Visual Studio.net để phát triển các dịch vụ web XML, ứng dụng trên nền Windows hay trên nền web một cách dễ dàng và hiệu quả. 1.1.2 Giới thiệu về Visual Studio.NET Visual Studio .NET là môi trường tích hợp phát triển phần mềm (Integrated Development Environment (IDE) ) của Microsoft ,là công cụ cho phép ta viết mã, gỡ rối và biên dịch chương trình trong nhiều ngôn ngữ lập trình .NET khác nhau .NET Framework: .NET được developed từ đầu năm 1998, lúc đầu có tên là  Next Generation Windows Services (NGWS). Nó được thiết kế hoàn toàn từ con số không để dùng cho Internet. Ý tưởng của Microsoft là xây dựng một globally distributed system, dùng XML (chứa những databases tí hon) làm chất keo để kết hợp chức năng của những computers khác nhau trong cùng một tổ chức hay trên khắp thế giới. Những computers này có thể là Servers, Desktop, Notebook hay Pocket Computers, đều có thể chạy cùng một software dựa trên một platform duy nhất, độc lập với hardware và ngôn Tr n o n n n N – M – u – N 4 Bài giảng môn lập trình windows 1 ngữ lập trình. Đó là .NET Framework. Nó sẽ trở thành một phần của MS Windows và sẽ được port qua các platform khác, có thể ngay cả Unix  Để cung cấp một môi trường lập trình hướng đối tượng vững chắc, trong đó mã nguồn đối tượng được lưu trữ và thực thi một cách cục bộ. Thực thi cục bộ nhưng được phân tán trên Internet, hoặc thực thi từ xa.  Để cung cấp một môi trường thực thi mã nguồn mà tối thiểu được việc đóng gói phần mềm và sự tranh chấp về phiên bản. Thư viện lớp, một thành phần chính khác của .NET Framework là một tập hợp hướng đối tượng của các kiểu dữ liệu được dùng lại, nó cho phép ta có thể phát triển những ứng dụng từ những ứng dụng truyền thông command-line hay những ứng dụng có giao diện đồ họa (GUI) đến những ứng dụng mới nhất được cung cấp bởi ASP.NET. Common Language Runtime(CLR) CLR thực hiện quản lý bộ nhớ, quản lý thực thi tiểu trình, thực thi mã nguồn, xác nhận mã nguồn an toàn, biên dịch và các dịch vụ hệ thống khác. Những đặc tính trên là nền tảng cơ bản cho những mà nguồn được quản lý chạy trên CLR. CLR thúc đẩy việc mã nguồn thực hiện việc truy cập được bảo mật. ví dụ người sử dụng giái hạn rằng việc thực thi nhúng vào trong một trang web có thể chạy được hoạt hình trên màn hình nhưng không thể truy cập được dữ liệu riêng, tập tin hệ thống, hay truy cập mạng. Thƣ viện lớp .NET Framework Thư viện lớp .NET Framework là một tập hợp những kiểu dữ liệu được dùng lại và được kết hợp chặt chẽ với CLR. Thư viện lớp là hướng đối tượng cung cấp những kiểu dữ liệu mà mã nguồn được quản lý của ta có thể dẫn xuất. 1.2 Biên dịch và MSIL Trong .NET Framework, chương trình không được biên dịch vào các tập tin thực thi mà thay vào đó chúng được biên dịch vào những tập tin trung gian gọi là Microsoft Intermediate Language ( MSIL). Những tập tin MSIL được tạo ra từ C# cũng tương tự như các tập tin MSIL được tạo ra từ những ngôn ngữ khác của .NET. Mã nguồn C# được biên dịch vào MSIL khi ta build project. Mã này được lưu vào trong một tập tin trên đĩa. Khi ta chạy chương trình, thì MSIL được biên dịch một lần nữa, sử dụng trình biên dịch Just – In – Time (JIT). Do tất cả các ngôn ngữ .NET Framework cùng tạo ra sản phẩm MSIL giống nhau, nên kết quả là một đối tượng được tạo ra từ ngôn ngữ này có thể được truy cập hay được dẫn xuất từ một đối tượng của ngôn ngữ khác trong .NET. Tr n o n n n N – M – u – N 5 Bài giảng môn lập trình windows 1 1.3 Ngôn ngữ C# Ngôn ngữ C# khá đơn giản nhưng nó có ý nghĩa cao khi thực thi khái niệm lập trình hiện đại. C# bao gồm tất cả những hỗ trợ cho cấu trúc, thành phần component, lập trình hướng đối tượng. Những tính chất đó hiện diện trong một ngôn ngữ lập trình hiện đại. Trong ngôn ngữ C# mọi thứ liên quan đến khai báo lớp đều được tìm thấy trong phần khai báo của nó. Định nghĩa một lớp trong ngôn ngữ C# không đòi hỏi phải chia ra tập tin header và tập tin nguồn giống như trong ngôn ngữ C++. C# cũng hỗ trợ giao diện interface, nó được xem như một cam kết với một lớp cho những dịch vụ mà giao diện quy định. Trong ngôn ngữ C#, một lớp chỉ có thể kế thừa từ duy nhất một lớp cha, tức là không cho đa kế thừa, nhưng một lớp có thể thực thi nhiều giao diện. Khi một lớp thực thi một giao diện thì nó sẽ cung cấp chức năng thực thi giao diện. Trong ngôn ngữ C#, những cấu trúc cũng được hỗ trợ, nhưng khái niệm về ngữ nghĩa của nó thay đổi khác với C++. Trong C#, một cấu trúc được giới hạn là kiểu dữ liệu nhỏ gọn, và khi tạo thể hiện thì nó yêu cầu ít hơn về hệ điều hành với bộ nhớ so với một lớp. Một cấu trúc thì không thể kế thừa từ một lớp hay được kế thừa nhưng một cấu trúc có thể thực thi một giao diện. Ngôn ngữ C# cung cấp những đặc tính hướng thành phần (component - oriented), như là những thuộc tính, những sự kiện. Lập trình hướng thành phần được hỗ trợ bởi CLR cho phép lưu trữ metadata với mã nguồn cho một lớp. Tr n o n n n N – M – u – N 6 Bài giảng môn lập trình windows 1 BÀI 2: NGÔN NGỮ C# 2.1 Tại sao phải sử dụng ngôn ngữ C# Ngôn ngữ C# là một ngôn ngữ được dẫn xuất từ C và C++. # l n ôn n ữ n ản C# loại bỏ một vài sự phức tạp của các ngôn ngữ khác như C++, bao gồm loại bỏ những macro, template, đa kế thừa, lớp cơ sở ảo vì chúng là nguyên nhân gây ra sự nhầm lẫn. C# là ngôn ngữ đơn giản vì nó dựa trên nền tảng C và C++, C# khá giống về diện mạo, 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ừ C và C++. # l n ôn n ữ n ạ Điều gì làm cho một ngôn ngữ hiện đại? Những đặc tính như là 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. Nếu là người mới học lập trình có thể chúng ta sẽ cảm thấy những đặc tính trên phức tạp và khó hiểu. !Ghi chú: Con trỏ được tích hợp vào ngôn ngữ C++. Chúng cũng là nguyên nhân gây ra những rắc rối của ngôn ngữ này. C# loại bỏ những phức tạp và rắc rối phát sinh bởi con trỏ. Trong C#, bộ thu gom bộ nhớ tự động và kiểu dữ liệu an toàn được tích hợp vào ngôn ngữ, sẽ loại bỏ những vấn đề rắc rối của C++. # l n ôn n ữ ớn ố t ợn Những đặc điểm chính của ngôn ngữ hướng đối tượng (Object-oriented language) là sự đóng gói (encapsulation), sự kế thừa (inheritance), và đa hình (polymorphism). C# hỗ trợ tất cả những đặc tính trên. Phần hướng đối tượng của C# sẽ được trình bày chi tiết trong một chương riêng ở phần sau. # l n ôn n ữ mạn mẽ v ũn m m dẻo Như đã đề cập trước, với ngôn ngữ C# chúng ta chỉ bị giới hạn ở chính bởi bản thân hay là trí tưởng tượng của chúng ta. Ngôn ngữ này không đặt những ràng buộc lên những việc có thể làm. C# được sử dụng cho nhiều các dự án khác nhau như là tạo ra ứng dụng xử lý văn bản, ứng dụng đồ họa, bản tính, hay thậm chí những trình biên dịch cho các ngôn ngữ khác. # l n ôn n ữ ít từ k ó 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. Chúng ta có thể nghĩ rằng một ngôn ngữ có nhiều từ khóa thì sẽ mạnh hơn. Tr n o n n n N – M – u – N 7 Bài giảng môn lập trình windows 1 Điều này không phải sự thật, ít nhất là trong trường hợp ngôn ngữ C#, chúng ta có thể tìm thấy rằng ngôn ngữ này có thể được sử dụng để làm bất cứ nhiệm vụ nào. 2.3 Các bƣớc chuẩn bị cho chƣơng trình Khi tạo một chương trình trong C# hay bất kỳ ngôn ngữ nào khác, đều tuân theo các bước tuần tự sau: - Xác định mục tiêu của chương trình - Xác định những phương pháp giải quyết vấn đề - Tạo một chương trình để giái quyết vấn đề - Thực thi chương trình để xem kết quả 2.4 Chƣơng trình C# đơn giản Để bắt đầu tìm hiểu ngôn ngữ C# và tạo tiền đề cho các chương sau, ta sẽ xem chương trình C# đơn giản sau: Để bắt đầu với chương trình đầu tiên, ta phải cài đặt bộ Visual Studio.NET (2005), sau đó thực hiện tuần tự các bước sau: - Nhấn Start/ nhấn All Program - Chọn Microsoft Visual Studio 2005 - Từ menu File chọn New, chọn Project thì hình 1 xuất hiện. Từ hình 1 Tr n o n n n N – M – u – N 8 Bài giảng môn lập trình windows 1 using System; using System.Collections.Generic; using System.Text; namespace chuongtrinhdautien { class Program { static void Main(string[] args) { Console.WriteLine(" Welcome to C#"); } } } Lớp, đối tƣợng và kiểu dữ liệu (type) Điều cốt lõi của lập trình hướng đối tượng là tạo ra các kiểu mới, nó có thể là một bảng dữ liệu, một tiểu trình, hay một nút lệnh trong cửa sổ. Kiểu được định nghĩa như một dạng vừa có thuộc tính chung và các hành vi của nó. Cũng như nhiều ngôn ngữ lập trình hướng đối tượng khác, kiểu trong C# được định nghĩa là một lớp (class) và các thể hiện của từng lớp được gọi là đối tượng (object). Để định nghĩa một lớp trong C#, ta sử dụng từ khóa class, sau đó đến tên lớp. Thân của lớp được nằm trong dấu {}. Chú ý: sau khai báo lớp trong C# không có dấu ; Tr n o n n n N – M – u – N 9 Bài giảng môn lập trình windows 1 Phƣơng thức Hai thành phần chính cấu thành một lớp là thuộc tính hay phương thức. Phương thức chính là các hàm thành viên trong một lớp. Về bản chất, phương thức trong C# cũng giống như hàm trong C++. Trong ví dụ trên, chúng ta có một phương thức, nhưng đây là một phương thức đặc biệt đó là phương thức Main(). Khi chương trình thực thi, CLR gọi hàm Main() đầu tiên, hàm Main() là đầu vào của chương trình, và mỗi chương trình đều phải có một hàm Main(). Để khai báo một phương thức, ta phải xác định kiểu giá trị trả về, tên phương thức, và các tham số càn thiết cho phương thức thực hiện. Chú thích Một chương trình tốt là một chương trình có các dòng chú thích kèm theo. Các đoạn chú thích này sẽ không được biên dịch và cũng không tham gia vào chương trình. Mục đích chính của nó là làm cho đoạn mã nguồn rõ ràng và dễ hiểu. Cũng giống như trong C++, trong ngôn ngữ C# chúng ta có 2 cách chú thích. Để chú thích trên một dòng thì ta bắt đầu bằng 2 ký tự “//”. Khi trình biên dịch gặp 2 ký tự này thì sẽ bỏ qua dòng đó. Ví dụ: // khởi tạo đối tượng Để chú thích trên nhiều dòng thì ta bắt đầu bởi ký tự “/*” và kết thúc bởi “*/”. Ứng dụng Console Ví dụ đơn giản trên được gọi là ứng dụng Console, ứng dụng này giao tiếp với người dùng thông qua bàn phím và không có giao diện người dùng (GUI). Trong các chương trình xây dựng các ứng dụng nâng cao trên Windows hay trên Web thì ta mới sự dụng giao diện đồ họa. Trong giáo trình này, sẽ sử dụng thuần túy các ứng dụng console. Namespace .NET cung cấp một thư viện các lớp đồ sộ và thư viện này có tên là FCL ( Framework Class Library), trong đó Console là một lớp nhỏ trong thư viện. Do đó sẽ nảy sinh vấn đề là người lập trình không thể nhớ hết được tên của các lớp trong .NET Framework. Đặc biệt là sau này ta có thể tạo ra một lớp mà lớp này lại trùng với lớp đã có trong thư viện, điều này dẫn đến sự tranh chấp khi biên dịch vì C# chỉ cho phép một tên duy nhất. Giải pháp để giải quyết vấn đề là việc tạo ra một không gian tên namespace, namespace sẽ hạn chế phạm vi của 1 tên, làm cho tên này chỉ có ý nghĩa trong vùng đã định nghĩa. Toán tử ‘.’ Tr n o n n n N – M – u – N 10 Bài giảng môn lập trình windows 1 Toán tử „.‟ Được sử dụng để truy cập đến phương thức hay thuộc tính trong một lớp, và ngăn cách giữa tên lớp đến một namespace. Việc thực hiện này được viết theo hướng từ trên xuống (hay từ cao xuống thấp), trong đó mức đầu tiên là namespace, rồi đến lớp, đến phương thức,…tuy nhiên nếu ta đã khai báo namespace rồi thì ta hoàn toàn có thể bỏ qua không gian tên. Từ khóa using Để cho chương trình trở lên gọn hơn, không mất thời gian phải viết từng namespace cho từng đối tượng, C# cung cấp từ khóa using, sau từ khóa này là một namespace với mô tả đầy đủ trong cấu trúc phân cấp của nó. Ví dụ, khi ta bắt đầu mở một dự án mới, luôn xuất hiện: using System; C# là ngôn ngữ phân biệt chữ hoa và chữ thƣờng Giống như C,C++, C# là ngôn ngữ phân biệt chữ hoa với chữ thường. Khi ta viết sai, C# sẽ không tự sửa lỗi này, chúng chỉ báo cho ta biết đang bị lỗi tại vị trí đó khi chúng ta đưa vào chương trình gỡ rối. 2.5 Bài tập Bài 1: Nhập vào đoạn chương trình sau, hãy biên dịch nó, cho biết chương trình trên thực hiện điều gì? using System; namespace vidu1 { class vidu { static void Main(string[] args) { int bk = 4; const double PI = 3.14; double cvi, dtich; dtich = PI * bk * bk; cvi = 2 * bk * PI; //in ket qua Console.WriteLine(" Ban kinh = {0} la ", bk); Console.WriteLine(" dien tich = {0} la ", dtich); Console.WriteLine(" Chu vi = {0} la ", cvi); } } } Bài 2: Chương trình sau có lỗi, biên dịch và sửa lỗi class test { Console.WriteLine(“ Xin chao”); Consoile.Writeline(“Tam biet”); Tr n o n n n N – M – u – N 11 Bài giảng môn lập trình windows 1 } Bài 3: Xuất ra màn hình bài thơ sau: Rằm tháng giêng Rằm xuân lồng lộng trăng soi Sông xuân nước lẫn màu trời thêm xuân Giữa dòng bàn bạc việc quân Khuya về bát ngát trăng ngân đầy thuyền. Tr n o n n n N – M – u – N 12 Bài giảng môn lập trình windows 1 CHƢƠNG 3: CƠ BẢN VỀ C# Trong chương 2 chúng ta đã tìm hiểu sơ qua về chương trình C# đơn giản nhất. Trong chương này ta sẽ thảo luận về hệ thống kiểu dữ liệu, phân biệt kiểu dữ liệu xây dựng sẵn với kiểu dữ liệu do người dùng định nghĩa. Một số vấn đề cơ bản về tạo và sử dụng biến, hằng, biểu thức và câu lệnh. 3.1 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à ngôn ngữ phải khai báo kiểu của mỗi đối tượng khi khởi tạo và trình biên dịch sẽ 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 và khả năng hoạt động của nó. Kiểu dữ liệu trong C# được chia thành 2 loại: kiểu xây dựng sẵn (built – in ) và kiểu dữ liệu do người dùng định nghĩa (user – defined ). C# phân tập hợp kiểu dữ liệu này thành 2 loại: kiểu dữ liệu giá trị và kiểu dữ liệu tham chiếu. Lý do của việc phân chia này là do sự khác nhau khi lưu kiểu dữ liệu giá trị và kiểu dữ liệu tham chiếu trong bộ nhớ. Đối với kiểu dữ liệu giá trị thì được lưu giữ kích thước thật trong bộ nhớ đã cấp phát là stack, trong khi đó thì địa chỉ của kiểu dữ liệu tham chiếu thì được lưu trong stack nhưng đối tượng thật thì lưu trong bộ nhớ heap. Chú ý: Tất cả các kiểu dữ liệu xây dựng sẵn đều là kiểu dữ liệu giá trị (trừ các đối tượng và chuỗi), còn tất cả các kiểu do người dùng định nghĩa (trừ kiểu cấu trúc) đều là kiểu dữ liệu tham chiếu. Trong chương này chúng ta quan tâm đến kiểu dữ liệu xây dựng sẵn. C# đưa ra các kiểu dữ liệu xây dựng sẵn rất hữu ích, phù hợp với 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ợ trong .NET. Việc ánh xạ các kiểu dữ liệu nguyên thủy 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. Mỗi kiểu dữ liệu có môt sự xác nhận và kích thước không thay đổi. Bảng mô tả các kiểu dữ liệu 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: 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: -128 đến 127 Tr n o n n n N – M – u – N 13 Bài giảng môn lập trình windows 1 short 2 Int16 Số nguyên có dấu giá trị từ - 32768 đến 32767 ushort 2 Uint16 Số nguyên không dấu: 0 – 65.535 int 4 Int32 Số nguyên có dấu từ - 2.147.483.647 đến 2.147.483.647 uint 4 Uint32 Số nguyên không dấu: 0 – 4.294.967.295 float 4 Single Kiểu chấm động, giá trị xấp xỉ từ 3,4E-38 đến 3,4E38 với 7 chữ số có nghĩa double 8 Double Kiểu chấm động có độ chính xác gấp đôi, giá trị từ 1,7E-308 đến 1,7E308, với 15 chữ số có nghĩa decimal 8 Decimal Có độ chính xác đến 28 chữ số, đượ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.808 đến 9.223.370.036.854.775.807 ulong 8 Uint64 Số nguyên không dấu: 0 đến 0xffffffffffffffff Chú ý: khác với C++, kiểu giá trị logic trong C# chỉ có thể nhận giá trị true hay false, chúng ta không thể gán một giá trị nguyên vào một biến kiểu logic trong C#. Chọn kiểu dữ liệu Chúng ta chọn kiểu dữ liệu dựa vào độ lớn của giá trị muốn sử dụng. Tùy vào miền giá trị và phạm vi sử dụng biến mà chọn các kiểu dữ liệu thích hợp nhất. Thông thường, kiểu dữ liệu int được sử dụng nhiều nhất trong lập trình vì với kích thước 4 byte thì nó cũng đủ để lưu các giá trị nguyên cần thiết. Kiểu số nguyên có dấu thường được lựa chọn sử dụng nhiều nhất trong kiểu số trừ( -) Kiểu số nguyên không dấu được sử dụng với các giá trị của biến dương. Kiểu float, double, decimal đưa ra nhiều mức độ khác nhau về kích thước cũng như độ chính xác. Trong C#, trình biên dịch 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 chúng ta khai báo rõ ràng Chú ý: để khai báo kiểu float thì sau giá trị phải cso ký tự „f‟ theo sau. Ví dụ: float PI = 3.14f; 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 dấu nháy đơn. Một số ký tự thoát đặc biệt: Tr n o n n n N – M – u – N 14 Bài giảng môn lập trình windows 1 Ký tự Ý nghĩa \‟ Dấu nháy đơn /‟‟ Dấu nháy kép \\ Dấu chéo \0 Ký tự null \n Dòng mới \r Đầu dòng \t Tab ngang \v Tab dọc Chuyển đổi kiểu dữ liệu Những đối tượng của một kiểu dữ liệu 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 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ẽ tự thực hiện công việc này. Còn chuyển đổi tường minh diễn ra khi ta 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 không mất mát thông tin. Ví dụ: short x = 10; int y=x; // chuyển đổi ngầm định Tuy nhiên việc chuyển đổi ngược lại chắc chắn sẽ bị mất mát thông tin, vì 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. Khi đó trình biên dịch sẽ không thực hiện việc chuyển đổi ngầm định từ kiểu int sang kiểu short. short x; int y = 100; x = y; // lỗi, không biên dịch Để chương trình có thể thực hiện được, ta phải chuyển đổi tường minh: short x; int y = 300; x = (short)y; //ép kiểu tường minh Tr n o n n n N – M – u – N 15 Bài giảng môn lập trình windows 1 3.2 Biến và hằng 3.2.1 Biến Một biến là một vùng lưu trữ với một kiểu dữ liệu. Biến có thể được gán giá trị và cũng có thể thay đổi giá trị khi thực hiện các lệnh trong chương trình. Để tạo một biến ta phải khai báo kiểu của biến và gán cho biến một tên duy nhất. Biến có thể được khởi tạo giá trị ngay khi được khai báo hay nó cũng có thể được gán với giá trị mới vào bất cứ lúc nào trong chương trình. Khai báo biến: = ; Ví dụ: int x,y,z; double f = 3.2; C# đòi hỏi các biến phải được khởi tạo trước khi sử dụng. Việc sử dụng biến khi chưa được khởi tạo là không hợp lệ trong C#. Tuy nhiên không nhất thiết lúc nào cũng phải khởi tạo biến. Nhưng để dùng được thì bắt buộc phải gán giá trị cho biến trước khi có một lệnh nào tham chiếu đến biến đó. 3.2.2 Hằng Hằng là một biến nhưng giá trị của hằng không thay đổi. Biến là công cụ rất mạnh nhưng khi làm việc với một giá trị được định nghĩa là không thay đổi trong suốt chương trình khi đó chúng ta sẽ sử dụng hằng. Để tạo một hằng, ta sử dụng từ khóa const và có cú pháp khai báo như sau: = ; Một hằng phải được khởi tạo khi khai báo và chỉ khởi tạo duy nhất một lần trong suốt chương trình và không thay đổi. Ví dụ ta khai báo hằng số pi trong toán học: const double pi = 3.14; 3.3 Định danh (tên) Định danh là tên mà người lập trình chỉ định cho các kiểu dữ liệu, các phương thức, biến, hằng hay đối tượng… Một định danh phải bắt đầu với một ký tự chữ cái hay dấu gạch dưới, các ký tự đi theo nó phải là các ký tự chữ cái, chữ số, dấu gạch dưới. Các định danh không được trùng với các từ khóa mà C# đưa ra, ngoài ra C# cũng phân biệt chữ hoa và chữ thường nên chú ý 2 biến PI và pi là khác nhau. 3.4 Biểu thức Những câu lệnh 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 được gọi là một biểu thức. Tr n o n n n N – M – u – N 16 Bài giảng môn lập trình windows 1 Ví dụ: x = 10; Trong câu lệnh trên phép đánh giá chính là phép gán có giá trị 10 cho biến x. Chú ý toán tử gán “=” không phải là toán tử so sánh nên khi sử dụng toán tử này thì giá trị bên phải được gán cho biến bên trái. Chúng ta cũng có thể thực hiện nhiều lệnh gán trong một biểu thức như a=b=c=d=10; Trong trường hợp này cả 4 biến đều nhận cùng một giá trị là 10. 3.5 Khoảng trắng Trong C# những khoảng trắng, khoảng tab và các dòng được xem như là khoảng trắng (whitespace). C# sẽ bỏ qua tất cả các khoảng trắng đó. Do đó 2 cách viết sau là như nhau: x=5; Hay x = 5; Tuy nhiên khoảng trắng trong một chuỗi sẽ không được bỏ qua. Việc sử dụng khoảng trắng là tùy ý của người lập trình để làm cho chương trình dễ nhìn hơn. Tuy nhiên cũng cần chú ý khi sử dụng khoảng trắng như sau: int x = 24; Khác với intx = 24; Trình biên dịch có thể bỏ qua khoảng trắng ở 2 bên của phép gán nhưng khoảng trắng giữa khai báo kiểu và tên biến thì tối thiểu phải có một khoảng trắng. Cũng giống như C++, trong C# câu lệnh hay biểu thức được kết thúc bởi dấu chấm phẩy „;‟. Do vậy có thể viết một câu lệnh trên nhiều dòng hay nhiều câu lệnh trên một dòng nhưng trong 2 câu lệnh nhất thiết phải cách nhau một dấu chấm phẩy. 3.6 Toán tử 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. 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ị theo toán hạng bên phải. Toán tử gán là toán tử 2 ngôi, đây là toán tử thông dụng nhất và dễ sử dụng nhất. Toán tử toán học  Các phép toán số học cơ bản (+,-,*,/): các phép toán này không thể thiếu trong bất cứ ngôn ngữ lập trình nào. Các phép toán số học đơn giản gồm: phép cộng, trừ, nhân, chia. Chú ý trong phép chia 2 số nguyên, C# sẽ bỏ qua phần dư, chỉ lấy phần nguyên. Tr n o n n n N – M – u – N 17 Bài giảng môn lập trình windows 1  Phép chia lấy dư (%): để tìm phần dư trong phép chia chúng ta sẽ sử dụng toán tử chia lấy dư. Ví dụ ta có phép toán 8%5 thì kết quả trả về là 3. Phép chia lấy dư rất có ý nghĩa đối với người lập trình. Thông thường ta hay sử dụng nó trong các vòng lặp. Toán tử tăng và giảm Khi sử dụng các biến số ta thường có thao tác cộng hay trừ đi một giá trị vào biến đó, hay thực hiện các tính toán thay đổi giá trị của biến sau đó gán giá trị mới vừa tính toán cho chính biến đó. Ta có bảng liệt kê các phép toán tự gán sau: Chúng ta cũng có phép tăng, giảm đi một đơn vị: ++: tăng 1 đơn vị --: giảm 1 đơn vị Toán tử quan hệ Những toán tử quan hệ được dùng để so sánh giữa 2 giá trị, kết quả trả về kết quả là một giá trị logic. Một số toán tử logic được trình bày trong bảng sau: Tr n o n n n N – M – u – N 18 Bài giảng môn lập trình windows 1 Lưu ý toán tử so sánh bằng được ký hiệu bởi 2 dấu = (==). Toán tử logic Trước khi tìm hiểu toán tử logic, chúng ta xem lại bảng chân lý sau: a b a and b a or b True True True True True False False True False True False True False False False False Trong ngôn ngữ C# cũng có các toán tử logic and, or, not nhưng chúng được ký hiệu bởi các ký tự: Trong bảng trên, giả sử x = 5, y = 7. Độ ƣu tiên của toán tử Trong một biểu thức luôn luôn tồn tại nhiều toán tử, khi đó trình biên dịch phải xác định xem toán tử nào được thực hiện trước, toán tử nào thực hiện sau. Khi đó chúng ta phải xác định được độ ưu tiên của toán tử. Các luật về độ ưu tiên xử lý sẽ bảo trình biên dịch biết được toán tử nào được thực hiện trước trong biểu thức. Tr n o n n n N – M – u – N 19 Bài giảng môn lập trình windows 1 Trong ngôn ngữ C#, dấu ngoặc được sử dụng để thay đổi thứ tự xử lý, nên trong một vài trường hợp, chúng ta nên sử dụng dấu ngoặc để cho biểu thức được rõ ràng. Bảng sau sẽ liệt kê độ ưu tiên của các phép toán trong C# Các phép toán cùng loại được liệt kê cùng loại sẽ có thứ tự theo mục thứ tự của bảng: thứ tự trái tức là độ ưu tiên của phép toán từ bên trái sang, thứ tự phải thì phép toán có độ ưu tiên từ bên phải sang. Các toán tử khác loại thì có độ ưu tiên từ trên xuống dưới, do vậy các toán tử loại cơ bản sẽ có độ ưu tiên cao nhất và phép gán sẽ có độ ưu tiên thấp nhất trong các toán tử. Toán tử điều kiện (toán tử 3 ngôi) Hầu hết các toán tử đòi hỏi có một toán hạng (như toán tử ++, --) hay 2 toán hạng (+.-,*,/) nhưng C# còn cung cấp thêm một toán tử có 3 toán hạng (?:). Toán tử trên có cú pháp như sau: ? < biểu thức 1> : Toán tử này sẽ xác định giá trị của một biểu thức điều kiện, biểu thức điều kiện này phải trả về một giá trị kiểu bool. Khi điều kiện đúng (biểu thức điều kiện trả về giá trị true) thì sẽ được thực hiện, ngược lại thì được thực hiện. Có thể Tr n o n n n N – M – u – N 20 Bài giảng môn lập trình windows 1 diễn giải toán tử này theo ngôn ngữ tự nhiên như sau: “ Nếu điều kiện đúng thì thực hiện công việc thứ nhất, còn ngược lại điều kiện sai thì thực hiện công việc thứ 2”. Ví dụ: static void Main(string[] args) { int x = 10; int y = 20; int max; max = x > y ? x : y; Console.WriteLine(" Gia tri lon nhat trong 2 so {0} va {1} la {2}", x, y, max); } Kết quả trả về: giá trị lớn nhất trong 2 số 10 và 20 là 20. Trong ví dụ trên, toán tử điều kiện được sử dụng để kiểm tra xem giá trị x có lớn hơn giá trị y không, nếu đúng thì trả về giá trị của x, tức là gán x cho biến max, còn ngược lại thì gán giá trị của y cho biến max. 3.7 Nhập xuất dữ liệu 3.7.1 Xuất dữ liệu ra màn hình Để xuất dữ liệu ra màn hình, ta sử dụng câu lệnh: Console.WriteLine(“ ”); Để xuất thông tin kiểu chuỗi ký tự thì rất đơn giản, ví dụ muốn xuất ra dòng “ Welcome to C#” ra màn hình thì ta chỉ cần 1 dòng: Console.WriteLine(“ Welcome to C#”); Chú ý: phải có dấu ngoặc kép “”, nếu không, trình biên dịch sẽ báo lỗi. Để xuất ra giá trị của biến, chúng ta có dạng như sau: Ví dụ: Console.WriteLine(" Gia tri lon nhat trong 2 so {0} va {1} la {2}", x, y, max); Chú ý: các số 0,1,2 ở trong dấu {} cho biết thứ tự in ra trên màn hình. 3.7.2 Nhập dữ liệu từ bàn phím Ví dụ có khai báo string s; int x; Để nhập vào một chuỗi: s= Console.ReadLine(); Hay để nhập vào một số nguyên: x = Int32.Parse(Console.ReadLine()); Tr n o n n n N – M – u – N 21 Bài giảng môn lập trình windows 1 Chúng ta thấy rằng, đối với mỗi một đối tượng khác nhau thì chúng ta sẽ nhập dữ liệu vào từ bàn phím khác nhau. Sau đây ta có bảng tương ứng đối với một kiểu dữ liệu khác nhau: short a a = Int16.Parse(Console.ReadLine()); ushort a a= UInt16.Parse(Console.ReadLine()); uint a a= UInt32.Parse(Console.ReadLine()); long a a = Int64.Parse(Console.ReadLine()); ulong a a= Uint64.Parse(Console.ReadLine()); string s s = Console.ReadLine(); char ch ch = Char.Parse(Console.ReadLine()); ch = char.Parse(Console.ReadLine()); float a a = float.Parse(Console.ReadLine()); a = Single.Parse(Console.ReadLine()); double a a = Double.Parse(Console.ReadLine()); a= double.Parse(Console.ReadLine()); 3.7.3 Ví dụ Ví dụ 1: Nhập vào bán kính của hình tròn, tính chu vi và diện tích của hình tròn đó. static void Main(string[] args) { double r; const double PI = 3.14;// khai báo hằng double DT, CV; Console.WriteLine("nhap vao ban kinh hinh tron: "); r = Double.Parse(Console.ReadLine());//nhập vào bán kính DT = PI * r * r; CV = 2 * PI * r; Console.WriteLine(" ban kinh hinh tron la :{0}", r);//in bk Console.WriteLine("Chu vi hinh tron: {0} \nDien tich hinh tron :{1}", CV, DT);//in ra chu vi và diện tích } Ví dụ 2: Nhập vào 2 số nguyên bất kỳ, hãy tính tổng, hiệu, tích, thương và số dư của 2 số đó. static void Main(string[] args) { int a, b; double tong, hieu, tich, thuong,du; Console.WriteLine("Nhap vao 2 so nguyen "); Console.Write(" Nhap so thu nhat:"); a = Int32.Parse(Console.ReadLine()); Console.Write("Nhap so thu 2:"); b = Int32.Parse(Console.ReadLine()); tong = a + b; Tr n o n n n N – M – u – N 22 Bài giảng môn lập trình windows 1 hieu = a - b; tich = a * b; thuong = (double)a / b;// chuyển đổi kiểu tường minh du = a % b; Console.WriteLine(" Tong a+b = {0}\nHieu a-b = {1}\nTich a*b = {2}\nThuong a/b = {3}\nSo du a%b = {4}", tong, hieu, tich, thuong, du); } 3.8 Câu lệnh (statement) Trong C#, một chỉ dẫn lập trình đầy đủ được gọi là câu lệnh. Chương trình bao gồm nhiều câu lệnh tuần tự với nhau. Mỗi câu lệnh phải kết thúc bởi dấu chấm phẩy „;‟. 3.8.1 Cấu trúc điều kiện Câu lệnh phân nhánh điều kiện 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 kiểm tra là đúng thì câu lệnh hay khối câu lệnh bên trong câu lệnh if được thực hiện. 3.8.1.1 Cú pháp lệnh điều kiện * Cấu trúc điều kiện if: + if (biểu thức điều kiện) lệnh 1; + if (biểu thức điều kiện ) { Lệnh 1; Lệnh 2; } * Cấu trúc điều kiện if else: + if (biểu thức điều kiện ) lệnh 1; else lệnh 2; * Cấu trúc điều kiện if else lồng nhau: + if (biểu thức điều kiện 1) if ( biểu thức điều kiện 2) if (biểu thức điều kiện n) lệnh 1; else lệnh 2; else lệnh 3; else lệnh 4; Tr n o n n n N – M – u – N 23 Bài giảng môn lập trình windows 1 3.8.1.2 Lƣu đồ thuật toán Lưu đồ thuật toán cho lệnh if đúng BTĐK Lệnh sai Lưu đồ thuật toán cho lệnh if … else false true BTĐK Lệnh 2 Lệnh 1 3.8.1.3 Ví dụ Ví dụ 1: Tìm giá trị lớn nhất của 2 số static void Main(string[] args) { int x, y, max; Console.Write("Nhap so thu 1:"); x = Int32.Parse(Console.ReadLine()); Console.Write("Nhap so thu 2:"); y = Int32.Parse(Console.ReadLine()); if (x > y) max = x; else max = y; Console.WriteLine("Gia tri max = {0}", max); } Ví dụ 2: Giải phương trình bậc nhất có dạng: ax + b = 0 với a, b được nhập từ bàn phím. Tr n o n n n N – M – u – N 24 Bài giảng môn lập trình windows 1 static void Main(string[] args) { double a, b; Console.Write("nhap he so a:"); a = Double.Parse(Console.ReadLine()); Console.Write("nhap he so b:"); b = Double.Parse(Console.ReadLine()); if (a == 0) if (b == 0) Console.WriteLine(" Phuong trinh vo so nghiem"); else Console.WriteLine(" Phuong trinh vo nghiem "); else Console.WriteLine(" Phuong trinh co 1 nghiem duy nhat la {0}", -b / a); } 3.8.1.4 Bài tập tự làm Bài 1: Hãy nhập vào điểm trung bình, xếp loại hạnh kiểm theo thang điểm sau: [0;5): yếu; [5;7): trung bình [7;8): khá [8;10]: giỏi Bài 2: Nhập vào 1 số, cho biết đó là số âm hay số dương Bài 3: Nhập vào 1 số, cho biết đó là số chẵn hay số lẻ. Bài 4: Nhập vào 3 số, tìm số lớn nhất? Bài 5: Nhập vào 3 số, cho biết đó có phải là 3 cạnh của tam giác hay không? Nếu là 3 cạnh của tam giác thì đó là tam giác gì?(cân, đều hay vuông) Bài 6: Nhập vào 1 ký tự bất kỳ, hãy cho biết ký tự đó thuộc loại nào?(chữ thường, chữ hoa hay chữ số). Bài 7: Nhập vào số nguyên n, kiểm tra xem n có phải là số chính phương không?(số chính phương là bình phương của số nguyên) Bài 8: Nhập vào họ tên và số điện các hộ tiêu dùng điện. Hãy in ra hóa đơn gồm họ tên, số điện và số tiền phải trả của các hộ biết rằng số tiền được tính như sau: 100kw đầu tiên giá 500đ/kw, 100kw tiếp theo giá 700đ/kw, trên 200kw giá 1000đ/kw. 3.8.2 Cấu trúc lựa chọn switch… case Lệnh lựa chọn switch… case trong C# thường sử dụng biến lựa chọn chủ yếu là kiểu nguyên. Tr n o n n n N – M – u – N 25 Bài giảng môn lập trình windows 1 Khi có quá nhiều điều kiện lựa chọn thì sử dụng cấu trúc điều kiện if …else trở lên phức tạp, dễ gây khó khăn cho người lập trình. Khi đó chúng ta sẽ sử 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. 3.8.2.2 Cú pháp switch ( biểu thức lựa chọn) { case : Lệnh 1; break; case : Lệnh 2; break; … case : Lệnh n; break; [default: lệnh khác; break;] } Cũng tương tự như câu lệnh if, biểu thức để lựa chọn được đặt sau từ khóa switch nhưng giá trị lựa chọn lại được đặt sau mỗi 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 lựa chọn sau switch thì các câu lệnh liên quan đến câu lệnh case này được thực thi. Tuy nhiên phải có một câu lệnh nhảy break để điều khiển nhảy qua các case khác. 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. 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 lệnh default thì các câu lệnh của trường hợp default sẽ được thực hiện. Ta thường dùng lệnh default để cảnh báo một 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. 3.8.2.2 Ví dụ Tr n o n n n N – M – u – N 26 Bài giảng môn lập trình windows 1 Ví dụ 1: Sử dụng cấu trúc switch… case để xếp loại học lực theo thang điểm như trong bài tập 1 trong mục 3.8.1.4 static void Main(string[] args) { int diem; Console.Write(" Nhap diem:"); diem = Int32.Parse(Console.ReadLine()); switch (diem) { case 0: case 1: case 2: case 3: case 4: Console.WriteLine(" Xep loai yeu "); break; case 5: case 6: Console.WriteLine("Xep loai trung binh "); break; case 7: Console.WriteLine("Xep loai kha "); break; case 8: case 9: case 10: Console.WriteLine("Xep loai trung binh "); break; default: Console.WriteLine(" Diem khong hop le"); break; } } Ví dụ 2: Viết chương trình nhập vào tháng và năm. Hãy cho biết tháng đó có bao nhiêu ngày? static void Main(string[] args) { int thang,nam; Console.WriteLine(" Nhap thang: "); thang = Int32.Parse(Console.ReadLine()); Console.WriteLine(" Nhap nam: "); nam = Int32.Parse(Console.ReadLine()); switch (thang) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: Console.WriteLine(" Co 31 ngay"); break; case 4: case 6: case 9: case 11: Tr n o n n n N – M – u – N 27 Bài giảng môn lập trình windows 1 Console.WriteLine(" Co 30 ngay"); break; case 2: if (nam % 4 == 0) Console.WriteLine(" Co 29 ngay"); else Console.WriteLine(" Co 28 ngay"); break; default: Console.WriteLine(" thang khong hop le"); break; } } 3.8.2.3 Bài tập tự làm Bài 1: Viết chương trình nhập ngày, tháng, năm hiện tại. Hãy cho biết ngày, tháng, năm của ngày tiếp theo. Bài 2: Viết chương trình nhập ngày, tháng, năm hiện tại. Đưa ra ngày, tháng, năm của ngày trước đó. 3.8.3 Cấu trúc lặp for Vòng lặp for bao gồm 3 thành 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ì sẽ thực hiện các lệnh bên trong vòng for - Thay đổi bước lặp 3.8.3.1 Cú pháp for ( biểu thức khởi tạo; biểu thức điều kiện; bước lặp) { Lệnh; } Đầu tiên, trình biên dịch sẽ duyệt biểu thức khởi tạo, kiểm tra xem biểu thức khởi tạo có thỏa mãn biểu thức điều kiện hay không, nếu đúng sẽ thực hiện lệnh và thực hiện lặp. Nếu không thỏa mãn sẽ thoát khỏi vòng lặp. Chúng ta cùng xem ví dụ sau: static void Main(string[] args) { int i; for (i = 0; i <= 30; i++) if (i % 10 == 0) Console.WriteLine("{0} ", i); else Console.Write("{0} ", i); Console.WriteLine(); } Tr n o n n n N – M – u – N 28 Bài giảng môn lập trình windows 1 Kết quả: Trong đoạn chương trình trên ta sử dụng toán tử chia lấy dư để kiểm tra i % 10==0 hay không, nếu i là bội số của 10 thì sử dụng lệnh WriteLine() để xuất ra giá trị i và sau đó đưa con trỏ về đầu dòng sau. Nếu không thì xuất giá trị i và không xuống dòng. Đầu tiên biến i được khởi tạo giá trị ban đầu là 0, sau đó chương trình sẽ kiểm tra điều kiện, do 0 <=30 nên điều kiện đúng khi đó câu lệnh trong vòng lặp for được thực hiện. Sau khi thực hiện xong thì biến i tăng lên 1 đơn vị (i++). 3.8.3.2 Lƣu đồ thuật toán Begin Biến đk = giá trị khởi tạo Biểu thức ĐK Sai End Đúng Lệnh Thay đổi biến điều kiện 3.8.3.3 Ví dụ Ví dụ 1: In ra dãy ký tự các chữ cái ra màn hình: abc…xyz ABC…XYZ ZYX…CBA zyx…cba static void Main(string[] args) { Tr n o n n n N – M – u – N 29 Bài giảng môn lập trình windows 1 char ch; for (ch = 'a'; ch <= 'z'; ch++) Console.Write("{0}", ch); Console.WriteLine(); for (ch = 'A'; ch <= 'Z'; ch++) Console.Write("{0}", ch); Console.WriteLine(); for (ch = 'z'; ch >= 'a'; ch--) Console.Write("{0}", ch); Console.WriteLine(); for (ch = 'Z'; ch >= 'A'; ch--) Console.Write("{0}", ch); Console.WriteLine(); } Kết quả: Ví dụ 2: Tính trung bình cộng của n số tự nhiên đầu tiên static void Main(string[] args) { int i, n; double tong=0, tbc; Console.Write("nhap n:"); n = Int32.Parse(Console.ReadLine()); for (i = 1; i <= n; i++) tong = tong + i; tbc = tong / n; Console.WriteLine("trung binh cong = {0}", tbc); } Kết quả: Ví dụ 3: Nhập vào 1 số nguyên, kiểm tra số đó có phải là số nguyên tố không? static void Main(string[] args) { int n, i; bool ng_to = true; Console.Write("Nhap n = "); n = Int32.Parse(Console.ReadLine()); for (i = 2; i <= Math.Sqrt(n); i++) if (n % i == 0) ng_to = false; if (ng_to == true) Console.WriteLine("{0} la so nguyen to ", n); Tr n o n n n N – M – u – N 30 Bài giảng môn lập trình windows 1 else Console.WriteLine("{0} khong la so nguyen to", n); } 3.8.3.4 Bài tập tự làm Bài 1: Tính n! Bài 2: Viết chương trình tính dân số của 1 thành phố sau 5 năm nữa biết rằng thành phố này hiện nay có 1,5 triệu dân, tỉ lệ tăng dân số hằng năm là 1%. Bài 3: Hãy sắp xếp 3 số được nhập vào từ bàn phím theo thứ tự tăng dần Bài 4: Tính tổng S = 1 + 1/2 + 1/3 + … + 1/n Bài 5: Tìm tất cả các số a, b, c thỏa mãn: tổng lập phương của các chữ số bằng chính số đó tức là : a3 + b3 + c3 = abc 3.8.4 Vòng lặp không xác định while Ý nghĩa của vòng lặp while là “ Trong khi điều kiện đúng thì thực hiện các công việc này”. 3.8.4.1 Cú pháp while (biểu thức điều kiện) { Lệnh; } Cách thực hiện: Chừng nào biểu thức còn đúng thì còn phải thực hiện công việc. 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. 3.8.4.2 Lƣu đồ thuật toán vòng lặp while Tr n o n n n N – M – u – N 31 Bài giảng môn lập trình windows 1 Begin S Biểu thức End Đ Công việc Chú ý: Vòng lặp while sẽ kiểm tra điều kiện trước khi thực hiện các lệnh bên trong, điều kiện 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. 3.8.5 Vòng lặp không xác định do … while Đôi khi vòng lặp while không thỏa mãn yêu cầu, chúng ta 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 tức là thực hiện 1 hành động rồi mới kiểm tra điều kiện. 3.8.5.1 Cú pháp do { Công việc; } 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. 3.8.5.2 Lƣu đồ thuật toán vòng lặp do… while Tr n o n n n N – M – u – N 32 Bài giảng môn lập trình windows 1 Begin Công việc Biểu thức Đ S End 3.9 Namespace Trong chương 2 đã nói qua về sử dụng đặc tính namespace trong C# nhằm tránh sự xung đột giữa việc sử dụng các thư viện khác nhau từ các nhà cung cấp. Ngoài ra namespace được xem như là tập hợp các lớp đối tượng và cung cấp duy nhất các định danh cho các kiểu dữ liệu và được đặt trong một cấu trúc phân cấp. Việc sử dụng namespace trong lập trình là một thói quen tốt vì công việc này chính là cách lưu các mã nguồn để sử dụng về sau. Ngoài thư viện namespace do MS.NET cung cấp, ta có thể tạo cho riêng mình các namespace. C# đưa ra từ khóa using để khai báo sử dụng namespace trong chương trình. Để tạo một namespace ta dùng cú pháp sau: namespace { <định nghĩa lớp A> <định nghĩa lớp B> …. } Ví dụ tạo một namespace namespace MyLib { using System; public class Tester { public static int Main() { Tr n o n n n N – M – u – N 33 Bài giảng môn lập trình windows 1 for (int i =0; i < 10; i++) { Console.WriteLine( “i: {0}”, i); } return 0; } } } Ví dụ trên tạo ra một namespace có tên là Mylib, bên trong namespace này chứa một lớp có tên là Test. Trong C# cho phép trong một namespace có thể tạo một namespace khác lồng bên trong và không giới hạn mức độ phân cấp này. Ví dụ: namespace MyLib { namespace Demo { using System; public class Tester { public static int Main() { for (int i =0; i < 10; i++) { Console.WriteLine( “i: {0}”, i); } return 0; } } } } Lớp Tester trong ví dụ 3.21 được đặt trong namespace Demo do đó có thể tạo một lớp Tester khác bên ngoài namespace Demo hay bên ngoài namespace MyLib mà không có bất cứ sự tranh cấp hay xung đột nào. Để truy cập lớp Tester dùng cú pháp sau: MyLib.Demo.Tester Tr n o n n n N – M – u – N 34 Bài giảng môn lập trình windows 1 CHƢƠNG 4: PHƢƠNG THỨC Phương thức cũng giống như hàm trong C++, nó gồm có 2 loại chính: phương thức trả về giá trị và phương thức kiểu void. Trong chương 4 này tất cả các phương thức đều có từ khóa static đứng trước kiểu vì tất cả các phương thức sử dụng ở đây đều thuộc phương thức tĩnh, không hướng đối tượng. Thuật ngữ phương thức (method) có thể gọi là “hàm” mà vẫn không làm lệch nội dung. 4.1 Khai báo phƣơng thức (danh sách tham số) { } Trong thân phương thức: + Chứa mã của phương thức + Chứa giá trị trả về nếu cần thiết + Được viết ở 1 vị trí khác ngoài phương thức Main()  Lý do phải sử dụng phương thức + Thực hiện chính sách “ chia để trị” + Sử dụng nhiều lần trong chương trình + Giảm việc lặp đi lặp lại, phương thức có thể được gọi từ bất kỳ chỗ nào trong chương trình. 4.2 Phƣơng thức trả về giá trị Phương thức này có kiểu float, double, int, string,… Bên trong phương thức luôn luôn có lệnh return để trả về một giá trị. static double Tong(double a,double b) { return a+b; } Do đó khi gọi phương thức cần khai báo 1 biến và gán tên phương thức cho biến. int m; Tr n o n n n N – M – u – N 35 Bài giảng môn lập trình windows 1 m = Tong(a,b); 4.3 Phƣơng thức kiểu void Có thể gọi phương thức kiểu void là phương thức không trả về giá trị, tuy nhiên nếu phương thức có đối số là tham chiếu thì nó có thể trả về nhiều giá trị đồng thời. Có thể chia phương thức kiểu void thành 4 loại: * Kiểu void không có đối số: Được dùng để hiển thị thông báo Ví dụ: void Thong_bao() { } * Kiểu void có đối số đưa vào nhưng không có đối số lây ra, nó thường dùng để hiển thị các thông báo, tính toán một biểu thức nào đó rồi hiển thị kết quả ra màn hình * Kiểu void không có đối số đưa vào nhưng có đối số lấy ra khỏi phương thức, nó thường dùng để nhập dữ liệu từ bàn phím và đưa ra khỏi phương thức. Các đối số lấy ra phải là đối số kiểu tham chiếu. * Kiểu void có cả đối số vào và đối số ra: Các đối số lấy ra phải là đối số kiểu tham chiếu. 4.4 Phạm vi của biến Phạm vi của biến là khoảng không gian tác dụng của biến trong chương trình. + Biến toàn cục: được sử dụng cho tất cả các phương thức + Biến địa phương: - Được tạo ra khi khai báo trong phương thức - Bị hủy khi thoát khỏi khối chương trình 4.5 Một vài phƣơng thức toán học thƣờng dùng trong lớp Math Cách dùng: .([tham số]) Một số hằng số: Math.PI = 3.1415… Math.E = 2.71828…. Một số phương thức của lớp Math: + Abs(x): trả về trị tuyệt đối của x + Ceiling(x): làm tròn x tới số tự nhiên nhỏ nhất không nhỏ hơn x. + Cos(x): tính lượng giác cosx + Exp(x): tính ex Tr n o n n n N – M – u – N 36 Bài giảng môn lập trình windows 1 + Floor(x): làm tròn tới số nguyên lớn nhất không vượt quá x + Log(x): tính logx + Max(x,y): Tìm giá trị lớn nhất giữa x và y + Min(x,y): tìm giá trị nhỏ nhất giữa x và y + Sin(x): tính sinx + Pow(x,y): tính xy + Sqrt(x): tính căn x + Tan(x): tính tgx Ví dụ: Tìm giá trị lớn nhất của 3 số( sử dụng phương thức toán học) static double Maximum(double x, double y, double z) { return Math.Max(x, Math.Max(y, z)); } static void Main(string[] args) { double a, b, c, max; Console.Write("Nhap a:"); a = Double.Parse(Console.ReadLine()); Console.Write("Nhap b:"); b = Double.Parse(Console.ReadLine()); Console.Write("Nhap c:"); c = Double.Parse(Console.ReadLine()); max = Maximum(a, b, c); Console.WriteLine("gia tri max = {0}", max); } 4.6 Ví dụ minh họa Ví dụ 1: Tính n! static double giai_thua(int n) { double gt=1; for (int i = 1; i <= n; i++) gt = gt * i; return gt; } static void Main(string[] args) { int n; Console.Write("Nhap n:"); n = Int32.Parse(Console.ReadLine()); Console.WriteLine(" n! = {0}", giai_thua(n)); } Ví dụ 2: Viết phương thức tính n!, sử dụng phương thức trên hãy tính giá trị của biểu thức sau: S = (n!+1)/(n+1)! Tr n o n n n N – M – u – N 37 Bài giảng môn lập trình windows 1 Ckn = n!/ (k!*(n-k)!) static double giai_thua(int n) { double gt=1; for (int i = 1; i <= n; i++) gt = gt * i; return gt; } static void Main(string[] args) { int n,k; Console.Write("Nhap n:"); n = Int32.Parse(Console.ReadLine()); Console.Write("Nhap k:"); k = Int32.Parse(Console.ReadLine()); double s, c; s = (giai_thua(n) + 1) / giai_thua(n + 1); c = giai_thua(n) / (giai_thua(k) * giai_thua(n - k)); Console.WriteLine(" s = {0}\n c = {1}", s, c); } 4.7 Truyền đối số kiểu tham chiếu có từ khóa ref hoặc out Như ta đã biết, tham số có kiểu dữ liệu là giát trị thì sẽ được truyền giá trị vào cho phương thức. Điều này có nghĩa rằng khi một đối tượng có kiểu là giá trị được truyền vào cho một phương thức, thì có một bản sao chép đối tượng đó được tạo ra bên trong phương thức. Một khi phương thức được thực hiện xong thì đối tượng sao chép này sẽ được hủy. Tuy nhiên, đây chỉ là trường hợp bình thường, ngôn ngữ C# còn cung cấp khả năng cho phép ta truyền các đối tượng có kiểu giá trị dưới hình thức là tham chiếu. Ngôn ngữ C# đưa ra một bổ sung tham số là ref cho phép truyền các đối tượng giá trị vào trong phương thức theo kiểu tham chiếu. Và tham số bổ sung out trong trường hợp muốn truyền dưới dạng tham chiếu mà không cần phải khởi tạo giá trị ban đầu cho tham số truyền. Ngoài ra ngôn ngữ C# còn hỗ trợ bổ sung params cho phép phương thức chấp nhận nhiều số lượng các tham số. Tru n t m ếu Những phương thức chỉ có thể trả về duy nhất một giá trị, mặc dù giá trị này có thể là một tập hợp các giá trị. Nếu chúng ta muốn phương thức trả về nhiều hơn một giá trị thì cách thực hiện là tạo các tham số dưới hình thức tham chiếu. Khi đó trong phương thức ta sẽ xử lý và gán các giá trị mới cho các tham số tham chiếu này, kết quả là sau khi phương thức thực hiện xong ta dùng các tham số truyền vào như là các kết quả trả về. Để truyền theo tham biến: - Gửi phương thức điểm quy chiếu thực sự của đối tượng - Phương thức trả lại luôn ở dạng tham chiếu - Từ khóa ref định nghĩa 1 tham chiếu Tr n o n n n N – M – u – N 38 Bài giảng môn lập trình windows 1 - Từ khóa out gọi tới 1 phương thức khi nó chưa khởi tạo giá trị ban đầu Để thấy được ý nghĩa của từ khóa ref và out, đầu tiên ta xét ví dụ sau đây không sử dụng tham chiếu với từ khóa ref và out: static void hoandoi(int a, int b) { int tg; tg = a; a = b; b = tg; Console.WriteLine(" Trong ham hoan doi: a = {0}, b = {1}", a, b); } static void Main(string[] args) { int a = 10, b = 20; Console.WriteLine(" Truoc khi hoan doi: a = {0}, b = {1}", a, b); hoandoi(a, b); Console.WriteLine(" Sau khi hoan doi: a = {0}, b = {1}", a, b); } Kết quả: Từ kết quả trên cho thấy bên trong hàm hoán đổi thì các giá trị của a và b được hoán đổi cho nhau, nhưng sau khi hoán đổi các giá trị của a và b lại như trước khi hoán đổi. Điều này cho thấy hàm hoán đổi không có tác dụng hoán đổi. Lý do là vì các tham số của hàm hoán đổi không sử dụng tham chiếu mà chỉ là các giá trị thông thường. Để khắc phục tình trạng trên, ta sử dụng 2 từ khóa để ref và out. * Từ khóa ref Từ khóa ref chỉ định tham số truyền vào phương thức dưới dạng tham biến. Mọi sự thay đổi về giá trị của tham số bên trong phương thức đều được giữ lại sau khi ra khỏi phương thức. Ví dụ: static void hoandoi(ref int a,ref int b) { int tg; tg = a; a = b; b = tg; Console.WriteLine(" Trong ham hoan doi: a = {0}, b = {1}", a, b); } static void Main(string[] args) { Tr n o n n n N – M – u – N 39 Bài giảng môn lập trình windows 1 int a = 10, b = 20; Console.WriteLine(" Truoc khi hoan doi: a = {0}, b = {1}", a, b); hoandoi(ref a,ref b); Console.WriteLine(" Sau khi hoan doi: a = {0}, b = {1}", a, b); } Kết quả: Nhận xét: bên trong hàm hoán đổi, các giá trị của a và b được hoán đổi cho nhau. Mặt khác sau khi gọi hàm hoán đổi, các giá trị của a và b cũng được hoán đổi. Điều này có nghĩa là hàm hoán đổi đã thực sự có tác dụng hoán đổi * Từ khóa out Từ khóa out cũng dùng để chỉ định tham số được truyền vào phương thức dưới dạng tham biến. Tuy nhiên sự khác biệt với từ khóa ref là tham số truyền vào không cần phải khởi tạo trước. Ví dụ: public class Time { public void DisplayCurrentTime() { Console.WriteLine(“{0}/{1}/{2} {3}:{4}:{5}”, Date, Month, Year, Hour, Minute, Second); } public int GetHour() { return Hour; } public void SetTime(int hr, out int min, ref int sec) { // Nếu số giây truyền vào >30 thì tăng số Minute và Second = 0 if ( sec >=30 ) { Minute++; Second = 0; Tr n o n n n N – M – u – N 40 Bài giảng môn lập trình windows 1 } Hour = hr; // thiết lập giá trị hr được truyền vào // Trả về giá trị mới cho min và sec min = Minute; sec = Second; } public Time( System.DateTime dt) { Year = dt.Year; Month = dt.Month; Date = dt.Day; Hour = dt.Hour; Minute = dt.Minute; Second = dt.Second; } // biến thành viên private private int Year; private int Month; private int Date; private int Hour; private int Minute; private int Second; } public class Tester { static void Main() { System.DateTime currentTime = System.DateTime.Now; Time t = new Time(currentTime); t.DisplayCurrentTime(); int theHour = 3; int theMinute; int theSecond = 20; t.SetTime( theHour, out theMinute, ref theSecond); Console.WriteLine(“The Minute is now: {0} and {1} seconds ”, theMinute, theSecond); theSecond = 45; t.SetTime( theHour, out theMinute, ref theSecond); Console.WriteLine(“The Minute is now: {0} and {1} seconds”, Tr n o n n n N – M – u – N 41 Bài giảng môn lập trình windows 1 theMinute, theSecond); } } 4.8 Bài tập Làm các bài tập trong chương 3 bằng cách xây dựng dưới dạng các phương thức. Tr n o n n n N – M – u – N 42 Bài giảng môn lập trình windows 1 CHƢƠNG 5: XÂY DỰNG LỚP – ĐỐI TƢỢNG 5.1 Lớp và đối tƣợng Trong chương 3 chúng ta đã được tìm hiểu về các kiểu dữ liệu cơ bản của C# như: int, float, double, string, char, … Tuy nhiên trái tim và linh hồn của C# là khả năng tạo ra những kiểu dữ liệu mới, phức tạp. Người lập trình tạo ra các kiểu dữ liệu mới bằng cách xây dựng các lớp đối tượng. Đây là khả năng để tạo ra những kiểu dữ liệu mới, một đặc tính quan trọng của ngôn ngữ lập trình hướng đối tượng. Chúng ta có thể xây dựng những kiểu dữ liệu mới trong ngôn ngữ C# bằng cách khai báo và định nghĩa lớp. Thể hiện của một lớp được gọi là những đối tượng (object), những đối tượng này được tạo trong bộ nhớ khi chương trình được thực hiện. Sự khác nhau giữa một lớp và một đối tượng cũng giống như sự khác nhau giữa khái niệm loài mèo và con mèo Mun. Chúng ta không thể đụng chạm hay tác động lên khái niệm mèo nhưng chúng ta hoàn toàn có thể hoàn làm được đối với 1 con mèo cụ thể. Một họ mèo mô tả những con mèo có các đặc tính: có trọng lượng, chiều cao, màu mặt, màu lông,… chúng có hành động là: ăn, ngủ, leo trèo,…Một con mèo có trọng lượng 1,5kg, cao 15cm, mắt màu đen, lông màu đen…và nó cũng có khẳ năng ăn, ngủ, leo trèo. Như vậy 1 đối tượng có đầy đủ các đặc tính và hành vi của 1 lớp. Trong chương này sẽ trình bày các đặc tính của ngôn ngữ C# để xây dựng các lớp đối tượng. Thành phần của 1 lớp bao gồm các hành vi và các thuộc tính được xem như là thành viên của lớp (class member). Đặc tính mới của ngôn ngữ C# đưa ra để xây dựng lớp là khái niệm thuộc tính (property), thành phần thuộc tính này hoạt động giống như phương thức để tạo 1 lớp nhưng bản chất của phương thức này là tạo 1 lớp giao diện cho bên ngoài tương tác với biến thành viên 1 cách gián tiếp. 5.1.1 Định nghĩa lớp Để định nghĩa 1 kiểu dữ liệu mới hay 1 lớp đầu tiên ta 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 đó. Cú pháp để khai báo 1 lớp (chú ý: tất cả các thành phần bên trong dấu [] có thể có hoặc không có): [thuộc tính truy cập] class tên_lớp [: lớp cơ sở] { } Tr n o n n n N – M – u – N 43 Bài giảng môn lập trình windows 1 5.1.2 Thuộc tính truy cập Thuộc tính truy cập quyết định khả năng 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 dưới đây sẽ tóm tắt các thuộc tính truy cập của 1 lớp trong C#: Thuộc tính Giới hạn truy cập 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 public 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 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 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 lớp A và bất cứ lớp nào trong cùng khối hợp ngữ của A protected internal Mong muốn chung là thiết kế các 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. C# xem thuộc tính private là mặc định khi khai báo các thuộc tính của lớp. Chú ý: Để lập trình tốt thì nên khai báo tường minh các thuộc tính truy cập của biến thành viên hay các phương thức trong 1 lớp. Mặc dù các thành viên của lớp được khai báo mặc định là private nhưng việc khai báo tường minh sẽ làm cho chương trình dễ hiểu, rõ ràng và tự nhiên hơn. Ví dụ tạo 1 lớp học sinh: class Hoc_sinh { private string hoten; private double diem; public void nhap() Tr n o n n n N – M – u – N 44 Bài giảng môn lập trình windows 1 {} public void xuat() {} } 5.1.3 Tạo đối tƣợng Trong chương 3 đã đề cập đến sự khác nhau giữa kiểu dữ liệu giá trị và kiểu dữ liệu tham chiếu. Những kiểu dữ liệu chuẩn như int, char, float, double,… 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. Cò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. Cú pháp: = new < Tên lớp>([danh sách tham số]); Ví dụ tạo 1 đối tượng thuộc lớp Hoc_sinh: Hoc_sinh hs = new Hoc_sinh(); 5.1.4 Sử dụng đối tƣợng Sử dụng toán tử „.‟ để sử dung dụng đối tượng Cú pháp: .([danh sách tham số]); Ví dụ: hs.nhap(); hs.xuat(); Ví dụ minh họa: Xây dựng lớp học sinh có các thuộc tính: tên, điểm toán, văn, điểm trung bình và có các phương thức nhập vào điểm toán, văn và phương thức xuất ra điểm trung bình. class Hoc_sinh { private string hoten; private double toan, van, dtb; public void nhap() { Console.Write("Nhap ten:"); hoten = Console.ReadLine(); Console.Write("Nhap diem toan:"); toan = Double.Parse(Console.ReadLine()); Console.Write("Nhap diem van:"); van = Double.Parse(Console.ReadLine()); } public void xuat() { Tr n o n n n N – M – u – N 45 Bài giảng môn lập trình windows 1 dtb = (toan + van) / 2; Console.WriteLine("Diem trung binh = {0}", dtb); } } class Test { static void Main(string[] args) { Hoc_sinh hs = new Hoc_sinh(); // tao doi tuong hs hs.nhap(); hs.xuat(); } } Ví dụ tự làm: Viết 1 lớp HCN có các thuộc tính là độ dài 2 cạnh và có các phương thức: + Nhập dữ liệu 2 cạnh cho hcn + Tính chu vi và diện tích hcn + In ra thông tin của hcn ra màn hình 5.2 Phƣơng thức khởi tạo (Constructor) Phương thức khởi tạo là phương thức có tên trùng với tên lớp của nó, các phương thức khởi tạo này sẽ tự động thực hiện khi đối tượng được sinh ra và chúng thường được dùng để khởi tạo giá trị ban đầu cho đối tượng. Các phương thức này được định nghĩa khi xây dựng lớp, nếu ta không tạo ra thì CLR sẽ tạo ra phương thức khởi tạo một cách mặc định. Chức năng của phương thức khởi tạo là tạo ra đối tượng xác định bởi một lớp và đặt trạng thái này hợp lệ. Trước khi phương thức khởi tạo được thực hiện thì đối tượng chưa được cấp phát trong bộ nhớ, sau khi phương thức này thực hiện hoàn thành thì bộ nhớ sẽ lưu giữ một thể hiện hợp lệ của lớp vừa khai báo. Thông thường khi muốn định nghĩa một phương thức khởi dựng riêng ta phải cung cấp các tham số để hàm khởi dựng có thể khởi tạo các giá trị khác ngoài giá trị mặc định cho các đối tượng. Phương thức khởi dựng không có giá trị trả về và được khai báo là public, nếu phương thức khởi tạo này được truyền tham số thì phải khai báo danh sách tham số giống như khai báo với bất kỳ phương thức nào trong 1 lớp. Một số đặc điểm của phương thức khởi tạo: - Không có giá trị trả về - Tên phương thức trùng với tên lớp - Có thể có hoặc không có tham số Tr n o n n n N – M – u – N 46 Bài giảng môn lập trình windows 1 - Khi gọi sử dụng chúng phải dùng từ khóa new Ví dụ minh họa: class Program { class vidu { private int a, b; public vidu() { a = 2; b = 3; } public vidu(int x, int y) { a = x; b = y; } public void show() { Console.WriteLine(" a = {0}\n b = {1}", a, b); } } static void Main(string[] args) { vidu vd = new vidu(); vd.show(); vd = new vidu(8, 5); vd.show(); } } Từ khóa this Từ khóa this được dùng để tham chiếu đến thể hiện của một đối tượng, tham chiếu this này được xem là con trỏ ẩn đến tất cả các phương thức không có thuộc tính tĩnh trong một lớp. Mỗi phương thức có thể tham chiếu đến những phương thức khác và các biến thành viên thông qua tham chiếu this này. Tham chiếu this được sử dụng thường xuyên theo các cách sau: * Sử dụng khi các biến thành viên bị che lấp bởi tham số đưa vào, tức là tên tham số đưa vào trùng với tên của biến thành viên Ví dụ: class thoigian { private int ngay, thang, nam; public void hienthi(int nam) { this.nam=nam; Tr n o n n n N – M – u – N 47 Bài giảng môn lập trình windows 1 } } Trong trường hợp này this.nam chỉ đến biến thành viên của đối tượng còn nam chỉ đến tham số. * Sử dụng tham chiếu this để truyền đối tượng hiện hành vào một tham số của phương thức của đối tượng khác. 5.3 Hủy đối tƣợng Ngôn ngữ C# cung cấp cơ chế thu dọn do đó không cần phải khai báo tường minh các phương thức hủy. Tuy nhiên khi làm việc với các đoạn mã không được quản lý thì cần phải khai báo tường minh các phương thức hủy để giải phóng tài nguyên. C# cung cấp ngầm định một phương thức để thực hiện công việc này đó là phương thức Finalize(). Phương thức Finalize() sẽ được gọi bởi cơ chế thu dọn khi đối tượng bị hủy. Phương thức hủy chỉ giải phóng các tài nguyên mà đối tượng nắm giữ, nó không tham chiếu đến các đối tượng khác. Nếu trong những đoạn mã chứa các tham chiếu kiểm soát được thì không cần thiết phải tạo và thực thi phương thức Finalize(), chúng ta chỉ làm điều này khi xử lý các tài nguyên không kiểm soát được. Chúng ta không gọi một phương thức Finalize() của 1 đối tượng một cách trực tiếp, trình thu dọn sẽ thực hiện việc gọi Finalize(). 5.3.1 Bộ hủy của C# Cú pháp của phương thức hủy trong C# cũng giống như trong C++, ta có thể khai báo 1 phương thức hủy trong C# như sau: ~class() {} Hoặc có thể viết class.Finalize() { base.Finalize(); } 5.4 Nạp chồng phƣơng thức Khi xây dựng các lớp ta mong muốn tạo ra nhiều hàm có cùng tên, ví dụ tạo ra nhiều phương thức khởi tạo chẳng hạn. Việc tạo ra nhiều phương thức có cùng tên gọi là nạp chồng phương thức. Tr n o n n n N – M – u – N 48