Ngôn ngữ lập trình C# GV: Tôn Quang Toại
Ngôn ngữ lập trình C#
GV: Tôn Quang Toại
2
Nội dung
Các thành phần cơ bản của ngôn ngữ Hệ thống kiểu Xuất/Nhập và chuyển đổi kiểu dữ liệu – chương trình
đầu tiên và giải thích Các lệnh điều khiển: if, switch, goto, for, do…while,
foreach Lớp, đối tượng và struct Đơn thừa kế Interface Property, Mảng và Indexer Lớp collection và exception Delegate và event
3
Ví dụ đầu tiên {1}
public class Hello1 {
public static void Main() {
System.Console.WriteLine("Hello, World!"); }
}
using System; public class Hello2 {
public static void Main() {
Console.WriteLine("Hello, World!"); }
}
4
Ví dụ đầu tiên {2}
using System; public class Hello3 {
public static void Main() {
Console.WriteLine("Hello, World!");Console.WriteLine(“So tham so: {0}: ", args.Length ); for (int i=0; i < args.Length; i++) {
Console.WriteLine("{0}", args[i]); }
} }
5
Ví dụ đầu tiên {3}
using System; public class Hello3 {
public static int Main() {
Console.WriteLine("Hello, World!");return 0;
} }
6
Ví dụ đầu tiên {4}
Hàm Main()• entry point của chương trình
• Được khai báo bên trong class hay struct
• Phải Static
• Kiểu trả về void hay int
• Có thể có hay không có tham số
Các thành phần cơ bản của ngôn ngữ
8
Identity {1}
Identity – định danh: Tên lớp, tên phương thức, tên biến, tên đối tượng, tên hằng, tên kiểu, …
Quy tắc tạo định dang trong C#: • Ký tự đầu tiên: chữ, ký tự gạch dưới, ký tự @
• Các ký tự còn lại: chữ, số, ký tự gạch dưới
9
Identity {2}
Một danh định có thể được đặt theo hai quy tắc • Pascal: Ký tự đầu tiên của mỗi từ viết HOA• Camel: Giống Pascal nhưng ký đầu tiên của danh định được
viết thường
Quy tắc đặt tên định danh• Pascal
– NameSpace– Class– Interface– Public Method/Field– Constant
• Camel– Otherss
10
Identity {2}
Quy tắc đặt tên định danh• Namespace
– Pascal– Tên của công ty + tên đề án cách nhau bằng ký
tự dấu chấm “.”
11
Identity {3}
Quy tắc đặt tên định danh• Interface
– Pascal– Bắt đầu bằng ký tự I
• Lớp– Pascal– Danh từ– Ví dụ:
Line, AudioSystem
12
Identity {4}
Quy tắc đặt tên định danh• Field
– Camel– Không chứa tên lớp– Ví dụ:
line, audioSystem
– Những biến có vai trò thì kết hợp vai trò với kiểu– Ví dụ:
Point startingPoint; Name loginName;
13
Identity {5}
Quy tắc đặt tên định danh• Field
– Những biến chung chung nên có cùng tên với kiểu– Ví dụ:
Topic topic; Database database;
– Những biến kiểu control: list, text, …: Nên kèm theo kiểu ở suffix
– Ví dụ: leftScrollbar
14
Identity {6}
Quy tắc đặt tên định danh• Field
– Mảng hay collection: Dùng danh từ số nhiều– Ví dụ:
Point[] points;
– Biến đếm: Dùng prefix: n, cnt– Ví dụ:
nPoints; cntPoint;
15
Identity {7}
Quy tắc đặt tên định danh• Phương thức
– Pascal– Động từ– Không chứa tên lớp– Khi phương thức truy cập field
Get/Set + field Dùng property
– Ví dụ: employee.getName();
16
Identity {8}
Quy tắc đặt tên định danh• Phương thức
– Khi phương thức trả về kiểu bool: Dùng prefix: Is, has, can, should
– Ví dụ: bool IsOpen(); bool ShouldAbort();
– Khi phương thức Tính toán: Dùng prefix: Compute Tìm kiếm: Dùng prefix: Find Thiết lập: Dùng prefix: Iniitialize
17
Identity {9}
Quy tắc đặt tên định danh• Đối số của phương thức
– Pascal
• Biến lặp trong phương thức– i, j, k, …
• Hằng giá trị– Viết HOA tất cả ký tự và có thể dùng thêm ký tự
Underscore
• Từ viết tắt– Chỉ viết HOA ký tự đầu– Ví dụ:– OpenDvdPlayer()
18
Biến – Biến hằng
Biến - Việc tạo biến trong C# có một số quy tắc sau:• Biến đươc khai báo trong khối cha thì không
được khai báo lại trong khối con và ngược lại.• Biến được khai báo trong vòng lặp for chỉ có
tác dụng trong vòng lặp for• Biến phải được khởi tạo trước khi sử dụng
Biến hằng:const int x =555;
19
Từ khóa - keyword
Có thể dùng "at" sign (@) ở đầu từ khóa để tạo identity
abstract as base bool break
by3 byte case catch char
checked class const continue decimal
default delegate do double descending3
explicit event extern else enum
false finally fixed float for
foreach from3 goto group3 if
implicit in int interface internal
into3 is lock long new
null namespace object operator out
override orderby3 params private protected
public readonly ref return switch
struct sbyte sealed short sizeof
stackalloc static string select3 this
throw true try typeof uint
ulong unchecked unsafe ushort using
var3 virtual volatile void while
where3 yield2
2 - C# 2.0 Keyword - 3 - C# 3.0 Keyword
20
Các toán tử C#
Loại toán tử Toán tử
Số học + - * / %
Logical (boolean và bitwise) & | ^ ! ~ && || true false
Nối chuỗi +
Tăng, giảm ++ --
Dịch chuyển bit << >>
Quan hệ == != < > <= >=
Gán = += -= *= /= %= &= |= ^= <<= >>= ?? (3.0)
Truy cập thành viên .
Chỉ mục, chỉ số []
Ép kiểu ()
Điều kiện ?:
Nối và gở bỏ delegate + -
Tạo đối tượng new
Thông tin kiểu as is sizeof typeof
Điều khiển ngoại lệ tràng bộ nhớ checked unchecked
Indirection và Address * -> [] &
Lambda => (3.5)
Hệ thống kiểu .NET
22
Mọi thứ đều là đối tượng {1}
Vấn đề: • Phần lớn các ngôn ngữ lập trình hướng đối
tượng có hai kiểu riêng biệt:– Các kiểu của riêng ngôn ngữ (kiểu cơ bản): ký
tự, chuỗi, số, … – Các kiểu do lập trình viên tạo ra (các lớp)
• Việc phân thành hai loại như thế một số vấn đề: Sự tương thích
23
Mọi thứ đều là đối tượng {2}
Vấn đề
• Ví dụ 1: Chúng ta muốn tạo một tập các số nguyên int và một tập các số thực double
• Ví dụ 2: Chúng ta muốn tạo một method có các tham số kiểu bất kỳ
24
Mọi thứ đều là đối tượng {3}
class CType{
public:CType(int data);CType(double data);CType(float data);
…};
class A{
public:void MyMethod(CType &type);
};
25
Mọi thứ đều là đối tượng {4}
.NET đã giúp chúng ta giải quyết vấn đề này dễ dàng hơn. • Mọi thứ trong CTS đều là đối tượng (không có
kiểu cơ bản nào cho từng ngôn ngữ trong .NET – tách kiểu ra khỏi ngôn ngữ)
• Tất cả đối tượng ngầm định được dẫn xuất từ duy nhất một lớp cơ sở được định nghĩa trong CTS: System.Object
26
Kiểu tham trị và kiểu tham chiếu {1}
27
Kiểu tham trị và kiểu tham chiếu {2}
Kiểu giá trị (value type):• Được cấp phát trên stack
• Ví dụ:– System.Int32 a = 5;
• Các loại kiểu giá trị:– enum– struct– kiểu cơ bản: int, double, …
28
Kiểu tham trị và kiểu tham chiếu {3}
Kiểu tham chiếu (reference type)• Các biến thuộc các kiểu tham khảo được cấp
phát trên vùng nhớ stack và biến trỏ đến một đối tượng đã được cấp trên vùng nhớ heap.
• Các biến thuộc các kiểu tham khảo có thể chứa giá trị null để báo rằng không trỏ đến đối tượng nào trên vùng nhớ heap
29
Kiểu tham trị và kiểu tham chiếu {4}
Kiểu tham chiếu (reference type)• Ví dụ :
– System.String s = “Hello, World”
• Các loại kiểu tham khảo:– Lớp– Mảng– Interface– Delegate
30
So sánh kiểu giá trị và kiểu tham chiếu
31
Boxing và Unboxing {1}
Vấn đề: việc tách thành hai loại kiểu như trên thì làm thế nào hệ thống hoạt động hiệu quả • Boxing: là chuyển từ kiểu giá trị sang kiểu
tham khảo
• Unboxing: là chuyển từ kiểu kiểu tham khảo sang giá trị
32
Boxing và Unboxing {2}
Boxing• Ví dụ:
– int a = 55;– object o = a;
• Quá trình hoạt động của boxing– Trước hết một vùng nhớ được cấp phát trên vùng nhớ
heap để tạo đối tượng o– Sau đó giá trị của biến kiểu giá trị được sao chép sang
vùng nhớ heap đó– Cuối cùng địa chỉ của đối tượng được cấp phát trên
heap được đặt vào vùng nhớ trên stack
33
Boxing và Unboxing {3}
Unboxing• Ví dụ:
– int a = 55;– object o = a;– int b = (int)o;
Chú ý: • Boxing là không cần ép kiểu• Unboxing phải ép kiểu
• Quá trình hoạt động của boxing– Trước hết runtime kiểm tra xem địa chỉ trên stack có trỏ đến đối tượng
hợp lệ không và kiểm tra xem kiểu đối tượng có thể được chuyển sang kiểu giá trị không. Nếu không sẽ nén ra một ngoại lệ InvalidCastException
– Một con trỏ đến giá trị bên trong đối tượng được trả về. Chú ý rằng boxing tạo một bản sao của kiểu được chuyển đổi, còn unboxing thì không làm thế.
34
Kiểu và bí danh {1}
CTS định nghĩa các kiểu cho tất cả các ngôn ngữ lập trình trên .NET như System.Int32, System.String, … nhưng mỗi ngôn ngữ lại chọn các bí danh trên các kiểu này
35
Kiểu và bí danh {2}
Kiểu C# và kiểu .NET Framework có thể dùng thay thế cho nhau
Để hiển thị kiểu .NET Framework của kiểu C# chúng ta dùng• Phương thức obj.GetType()
VD: int x= 5;x.GetType();
• Toán tử typeof(type) VD: typeof(int);
Kiều C# Kiểu .NET Framework
bool System.Boolean
byte System.Byte
sbyte System.SByte
char System.Char
decimal System.Decimal
double System.Double
float System.Single
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
object System.Object
short System.Int16
ushort System.UInt16
string System.String
36
Kiểu số nguyên
Kiểu Miền giá trị Kích thước (bit)
sbyte -128 to 127 8
byte 0 to 255 8
char U+0000 to U+ffff 16
short -32,768 to 32,767 16
ushort 0 to 65,535 16
int -2,147,483,648 to 2,147,483,647 32
uint 0 to 4,294,967,295 32
long-9,223,372,036,854,775,808 to
9,223,372,036,854,775,80764
ulong 0 to 18,446,744,073,709,551,615 64
37
Kiểu số thực
Kiểu Miền giá trị Độ chính xác Kích thước (bit)
float ±1.5e−45 to ±3.4e38 7 digits 32
double ±5.0e−324 to ±1.7e308 15-16 digits 64
38
Kiểu số decimal
So với các kiểu số thực, decimal có: • Độ chính xác cao hơn• Miền giá trị nhỏ hơn
Phù hợp cho các ứng dụng tài chính, tiền tệ Nếu muốn một số thực được xem như là decimal
dùng hậu tố m hay Mdecimal myMoney = 300.5m;
Số nguyên: tự chuyển đổidecimal myMoney = 300;
Chuyển đổi giữa Số thực và decimal ép kiểudecimal myMoney = 99.9m; double x = (double)myMoney; myMoney = (decimal)x;
Kiểu Miền giá trị Độ chính xác Kích thước (bit)
decimal ±1.0 × 10−28 to ±7.9 × 1028 28-29 128
39
Kiểu ký tự
Hằng ký tự: • ‘a’
• ‘\uxxxx’: x là số hexa
Kiểu Kích thước (bit)
char 16
40
Kiểu chuỗi
Đặc điểm string• Chuỗi ký tự unicode• Kiểu tham chiếu• Kích thước cố định
Hằng chuỗi:• “”• @””
Phép toán trên string• Toán tử ==, != dùng để so sánh các giá trị của string• +, []
41
Kiểu bool
Miền giá trị: true, false Không thể chuyển bool sang kiểu khác
Kiểu Kích thước (bit)
bool 1
42
Chuyển kiểu ngầm định
Không có chuyển kiểu ngầm định • Sang kiểu char
• Giữa số thực và decimal
43
Các giá tri mặc nhiên của kiểu giá trị {1}
Khi dùng constructor mặc nhiên, các biến thuộc kiểu dữ liệu giá trị sẽ có giá trị mặc nhiên
VD: int myInt = new int(); int myInt = 0;
Chú ý: Không được sử dụng biến chưa khởi tạo
44
Các giá tri mặc nhiên của kiểu giá trị {2}
kiểu giá trị Giá trị mặc nhiên
bool false
byte 0
char '\0'
decimal 0.0M
double 0.0D
enum Giá trị được sinh bởi biểu thức (E)0, trong đó E là identity của enum.
float 0.0F
int 0
long 0L
sbyte 0
short 0
structGiá trị được sinh bằng cách thiết lập tất cả field kiểu giá trị thanh giá trị
mặc nhiên, tất cả field kiểu tham chiếu thành null.
uint 0
ulong 0
ushort 0
Xuất/Nhập và chuyển đổi kiểu dữ liệuchương trình đầu tiên
46
Chương trình đầu tiên
namespace CSharp
{
class Program
{
public static void Main()
{
// Xuat du lieu ra man hinh
System.Console.WriteLine("Hello, World");
}
}
}
47
Giải thích – Cách viết code
One-Stop Programming• Các phương thức được định nghĩa ngay trong
thân của lớp
48
Giải thích – Namespace {1/2}
Namespace• Chức năng cơ bản là nhóm các thành phần
(lớp, struct, namespace khác, …) dưới 1 cái tên để tránh việc trùng tên của các thành phần
• Cú pháp:
namespace <namespace_name>
{
<namespace-body>
}
49
Giải thích – Namespace {2/2}
Chú ý:• Namespace có thể lồng namespace khác• Các thành phần trong các namespace khác nhau có
thể có tên giống nhau Để truy cập các thành phần bên trong namespace
chúng ta dùng cú pháp
Để viết code dễ dàng hơn chúng ta có thể dùng câu lệnh using• Cú pháp
<namespace_name1>.<namespace_name2>…<class>
using <NamespaceName>;
50
Giải thích – Chú thích
Giống C/C++
//
/**/
51
Giải thích – Lớp và thành viên
Một lớp C# có thể chứa các thành viên • Constants
• Fields
• Methods
• Properties
• Events
• Indexers
• Operators
• instance constructors
• destructors, static constructors và các kiểu khai báo lồng nhau
52
Giải thích – Phương thức Main
Phải có ít nhất một lớp chứa phương thức Main• public static void Main()
• public static void Main( string[] args )
• public static int Main()
• public static int Main( string[] args )
53
Giải thích – Xuất dữ liệu {1/3}
Nhập dữ liệu từ bàn phím và xuất dữ liệu ra màn hình trong C# có thể dùng các phương thức tĩnh trong lớp: System.Console
Xuất dữ liệu lên màn hình• Cú pháp 1:
void Write(data);
void WriteLine(data);
54
Giải thích – Xuất dữ liệu {2/3}
Xuất dữ liệu lên màn hình• Cú pháp 2:
• Trong đó:– format: chứa chuỗi định dạng– arg là mảng các đối tượng xuất sử dụng chuỗi
định dạng
void Write(string format, params object[]arg);
void WriteLine(string format, params object[]arg);
55
Giải thích – Xuất dữ liệu {3/3}
Xuất dữ liệu lên màn hình• format là một chuỗi bình thường và có thể có
thêm 1 hay nhiều phần định dạng có cú pháp sau
– Cú pháp:
– Trong đó: index: Số thứ tự của đối số, bắt đầu từ 0 alignment: độ rộng, M>0 canh phải, M<0 canh trái formatString: C hay c, D hay d, E hay e, F hay f, …
{ index[,alignment][:formatString]}
56
Giải thích – Nhập dữ liệu
Nhập dữ liệu từ bàn phím• Cú pháp:
int Read();
string ReadLine();
57
Lớp Convert
Đây là lớp tiện ích cho việc chuyển đổi giữa các dữ liệu có các kiểu dữ liệu khác nhau
Phương thức Ý nghĩa
ToBoolean Chuyển một giá trị sang giá trị Boolean
ToByte Chuyển một giá trị sang giá trị số nguyên 8-bit không dấu
ToChar Chuyển một giá trị sang giá trị ký tự unicode
ToDateTime Chuyển một giá trị sang giá trị DateTime.
ToDecimal Chuyển một giá trị sang giá trị Decimal.
ToDouble Chuyển một giá trị sang giá trị số thực có độ chính xác gấp đôi 8 byte
ToInt16 Chuyển một giá trị sang giá trị số nguyên 16-bit có dấu
ToInt32 Chuyển một giá trị sang giá trị só nguyên 32-bit có dấu
ToInt64 Chuyển một giá trị sang giá trị số nguyên 64-bit có dấu
ToSByte Chuyển một giá trị sang giá trị số nguyên 8-bit có dấu
ToSingle Chuyển một giá trị sang giá trị số thực có độ chính xác đơn
ToString Chuyển một giá trị sang giá trị một chuỗi
ToUInt16 Chuyển một giá trị sang giá trị số nguyên 16-bit không dấu
ToUInt32 Chuyển một giá trị sang giá trị số nguyên 32-bit không dấu
ToUInt64 Chuyển một giá trị sang giá trị số nguyên 64-bit không dấu
Các lệnh điều khiển: if, switch, goto, for, do…while, foreach
59
Câu lệnh if, switch
Cú pháp 1
Cú pháp 2
if (expression)
{
Các câu lệnh
}
if (expression)
{
Các câu lệnh A;
}
else
{
Các câu lệnh B;
}
60
Câu lệnh if, switch {1/2}
Câu lệnh if• Cú pháp 1
• Cú pháp 2
if (expression)
{
Các câu lệnh
}
if (expression)
{
Các câu lệnh A;
}
else
{
Các câu lệnh B;
}
61
Câu lệnh if, switch {2/2}
Câu lệnh switch• Cú pháp
Chú ý:• Expression phải thuộc các kiểu:
– số nguyên, char, string, enum
• Luôn cung cấp “lệnh nhảy” cho mỗi case (kể cả default)
• Nếu thân case là câu lệnh rỗng thì không cần lệnh nhảy
switch (expression){
case const_expression1:
…
break;
case const_expression2:
…
break;
…
case const_expressionN:
…
break;
default:
…
break;
}
62
Câu lệnh nhảy
Câu lệnh break, continue giống C/C++ Câu lệnh goto
• Cú pháp
goto label;
goto case constExpression
goto default;
63
Câu lệnh lặp {1/3}
Câu lệnh for• Cú pháp
Câu lệnh while• Cú pháp
for (initialization; BooleanExpression; step)
{
Các câu lệnh
}
while (BooleanExpression)
{
Các câu lệnh
}
64
Câu lệnh lặp {2/3}
Câu lệnh do...while• Cú pháp
do
{
Các câu lệnh
} while (BooleanExpression);
65
Câu lệnh lặp {3/3}
Câu lệnh foreach• Cú pháp
• Trong đó:– type là kiều của biến variableName– expression là đối tượng collection hay mảng
foreach (type variableName in expression)
{
Các câu lệnh
}
Lớp, đối tượng và struct
67
Định nghĩa lớp cơ bản
Định nghĩa lớp• Cú pháp:
Các thành viên của class • Field• Method• Property• Constant• Indexer• Event• Operator
[attributes] [modifiers] class <className> [: baseClassName]
{
[class-body]
}[;]
68
Bổ từ truy cập
Bổ từ truy cập• public
• protected
• private
• internal
DEFAULT: private
class AccessModsInCSharp {
public int a; public int b; public int c; protected int d; protected int e;
}
69
Lớp
Field• Khai báo thành viên dữ liệu giống như khai báo biến
• Cú pháp: <type> <name>;
• Trong đó <type> có thể là– Kiểu cơ sở: char, int, float, double, …– Enum– Struct– Class – Event
70
Dữ liệu của lớp - Field
Field• Thành viên dữ liệu có thể là một đối tượng
của lớp đang định
• Có thể vừa khai báo, vừa khởi tạo dữ liệu cho thành viên dữ liệu
71
Phương thức
Phương thức và tham số• Định nghĩa phương thức trong C# chí có 1
cách: Thân của phương thức nằm trong lớp
• Có hai loại tham số phương thức– Tham số giá trị: không có modefier – Tham số tham chiếu: ref, out, params
72
Phương thức
Phương thức với tham số params• Cú pháp
• Chú ý:– Khi dùng từ khóa params thì mảng theo
params là là tham số cuối cùng của phương thức.
class ClassName()
{
Method(…, params type[] variableName)
{
…
}
}
73
Phương thức
Phương thức với tham số ref• Cú pháp class ClassName()
{
Method(ref type variableName)
{
…
}
}
74
Phương thức
Phương thức với tham số ref• Cú pháp: sử dụng phương thức ref
• Chú ý – Tham số thực phải được khởi tạo trước khi gọi
phương thức.– Mọi thay đổi giá trị trong tham số hình thức đều
thay đổi giá trị trong tham số thực.– Giá trị của tham số thực được chuyển đến
tham số hình thức.
variableName = value;
Method(ref variableName);
75
Phương thức
Phương thức với tham số out • Cú pháp class ClassName()
{
Method(out type variableName)
{
…
variableName = value;
}
}
76
Phương thức
Phương thức với tham số out • Cú pháp: sử dụng phương thức out
• Chú ý– Tham số thực không nhất thiết phải được khởi tạo trước
khi gọi phương thức.– Tham số hình thức trong phương thức phải được gán
giá trị trước khi phương thức kết thúc– Giá trị của tham số thực không được chuyển đến tham
số hình thức, vì vậy không được dùng tham số hình thức trong hàm nếu chưa khởi tạo.
//variableName = value;
Method(out variableName);
77
Phương thức
Method overloading• Phương thức có cùng tên phương thức nhưng
khác nhau về chữ ký phương thức.
Chữ ký phương thức: • Số lượng các tham số,
• Kiểu dữ liệu của các tham số và
• Thứ tự của các tham số.
78
Phương thức Toán tử
Operator Overloading• Toán tử 1 ngôi
• Toán tử 2 ngôi
+ - ! ~
++ -- true false
+ - * / % &
| ^ << >> == !=
> < >= <=
79
Phương thức Toán tử
Cú phápusing System;public class Distance{ int longitude, latitude;
public Distance() { longitude = 0; latitude = 0; }
public Distance(int longitude, int latitude) {
this.longitude = longitude;this.latitude = latitude;
}
public static Distance operator - (Distance first, Distance second) {
return new Distance(first.longitude - second.longitude, first.latitude - second.latitude); }}
public static retval operator op (object1 [, object2])
80
Phương thức Toán tử
Tất cả các phương thức toán tử được định nghĩa: public và static
Khi overload toán tử 2 ngôi phép gán kết hợp được tự động overload
Toán tử so sánh (>, <, >=, <=, ==, !=) phải overload từng cặp
Nếu toán tử == và != được overload phải overload phương thức Equals() và GetHashCode()
81
Phương thức Constructor
Constructor • Cú pháp
• Chú ý– Construtor được gọi tự động khi một instance của lớp
được tạo. Không thể gọi phương thức constructor rõ ràng.
– Các constructor có thể được đa năng hóa để cung cấp sự đa dạng cho việc khởi tạo đối tượng.
– Phương thức constructor có thể gọi các phương thức construtor khác
class ClassName
{
public ClassName(…)
{….}
}
82
Phương thức Destructor
Destructor • Cú pháp
• Chú ý– Không có bất kỳ tham số nào– Được gọi bởi Garbage Collector - GC
class ClassName
{
public ~ClassName(…)
{….}
}
83
Đối tượng
Tạo đối tượng với từ khóa new • Khai báo một biến class
– Cú pháp
• Tạo một đối thật sự – Cú pháp
<ClassName> <ObjectName>;
<ObjectName> = new <ClassName>(…);
<ClassName> <ObjectName> = new <ClassName>(…);
84
Đối tượng
Truy cập thành viên class • Cú pháp
• Trong C# cũng có con trỏ this giống C++– Cú pháp
ObjectName.Method(params);
ObjectName.Field;
this.member
85
Các thành phần khác của lớp
Field và Phương thức tĩnh • Cú pháp class ClassName
{
public static type variableName;
public static type Method(…)
{
…
}
}
86
Các thành phần khác của lớp
Field và Phương thức tĩnh• Cú pháp: Gọi field và phương thức tĩnh
• Chú ý– Nếu không khai báo public thì phương
thức/field tĩnh chỉ được dùng cho các phương thức của lớp.
– Nếu phương thức gọi phương thức/field tĩnh thì dùng tên phương thức hay tên field không cần thông qua tên lớp
ClassName.Method(…);
ClassName.variableName;
87
Các thành phần khác của lớp
Constant• Hằng là một field có giá trị không thay đổi
trong chu kỳ sống của đối tượng
• Ví dụ: const int x = 5;
• Quy tắc: – Field hằng là field có giá trị được thiết lập lúc
biên dịch– Field hằng mặc nhiên là tĩnh
88
Các thành phần khác của lớp
Field Read-Only• Để field có giá trị được trì hoãn cho đến khi
chương trình bắt đầu chạy (khi đối tượng của lớp chứa field được tạo) chúng ta dùng field dạng readonly
• Giá trị của field được khởi tạo trong constructor
class CaptureApp{ public readonly int screenColor;
public CaptureApp(){
screenColor=65536;}
}
89
Các thành phần khác của lớp
Constructor tĩnh• Nếu một field là tĩnh thì phải có phương thức
constructor tĩnh.
• Constructor tĩnh là constructor để khởi tạo các field tĩnh và readonly
class CaptureApp{ public readonly int screenColor;
static CaptureApp(){
screenColor=65536;}
}
Thừa kế
91
Định nghĩa thừa kế
Định nghĩa • Cú pháp
Đơn thừa kế • C# không hổ trợ đa thừa kế thông qua dẫn
xuất• Tập hợp các đặc tính hành vi của các thực thể
được hiện thực bằng đa thừa kế giao diện
class DerivedClass : BaseClass{
…}
92
Gọi Construtor của lớp cơ sở
Tất cả các constructor trong C# có lời gọi constructor của lớp cơ sở
Bộ khởi tạo giúp chúng ta quyết định lớp nào và constructor nào muốn gọi. • base(…)
• this(…)
class ClassName{
public ClassName(type obj, …):base(…){….}
public ClassName(type obj, …):this(…)
{….}
}
93
Phương thức “new”
Phương thức trong lớp cơ sở và lớp dẫn xuất có thể trùng tên
Trình biên dịch sinh ra warning message cảnh báo IdentifierToken.Name ẩn Token.Name
class Token {
⋮public string Name() { ... }
} class IdentifierToken : Token {
⋮public string Name() { ... }
}
94
Phương thức “new”
Được dùng như là 1 toán tử hay 1 modifier new được dùng để ẩn đi thành viên được
thừa kế từ lớp cơ sở Một phương thức không thể đồng thời có
new và overrideclass Token {
⋮public string Name() { ... }
} class IdentifierToken : Token {
⋮new public string Name() { ... }
}
95
Phương thức “new”
static void Method(Token t) {
Console.WriteLine(t.Name()); } static void Main() {
IdentifierToken variable = new IdentifierToken("variable"); Method(variable);
}
96
Phương thức “virtual”
virtual được dùng để định nghĩa phương thức hổ trợ đa hình
Đa hình nghĩa là có thể hiện thực 1 phương thức nhiều lần
Các lớp con tự lo hiện thực phiên bản của riêng mình của phương thức virtual bằng cách dùng từ khóa override
97
Phương thức “virtual”
Virtual không thể được dùng với static và override
class Token {
⋮public virtual string Name() { ... }
}
Đây là phiên bản hiện thực đầu tiên của
phương thức Name()
98
Phương thức “override”
Một phương thức override cung cấp một thực thi mới cho phương thức của lớp cơ sở. Phương thức lớp cơ sở nên khái báo là virtual
Accessibility level của phương thức cơ sở không thể bị thay đổi bởi phương thức override nó
Từ khóa new, static, virtual không thể được dùng cùng override
99
Phương thức “override”
class IdentifierToken : Token {
⋮public override string Name() { ... }
}
Hiện thực khác của phương thức Name()
100
Phương thức “override”
Phương thức private không thể là virtual hay override
Hai phương thức phải: cùng tên, cùng kiểu và số lượng tham số, cùng kiểu trả về
Hai phương thức phải cùng kiểu truy cập Chỉ có thể override phương thức virtual override ngầm hiểu là virtual có thể
override ở những phương thức con tiếp theo
101
Đa hình
Để thực hiện tính đa hình chúng ta thực hiện các bước sau:• Phương thức trong lớp cha là phương thức
virtual, override hay abstract
• Phương thức trong lớp con là phương thức override
102
Đa hình
Cú pháp
class ClassName1{
virtual public type Method(…){}
}
class ClassName2: ClassName1{
override public type Method(…){}
}
103
Lớp sealed và abstract
Lớp trừu tượng• Lớp trừu tượng là lớp được khai báo để làm lớp cơ sở
cho lớp khác.
Chú ý:• Lớp trừu tượng không cho tạo đối tượng
• Khai báo phương thức trừu tượng chỉ trong lớp trừu tượng
• Thành viên trừu tượng không thể là static
• Phương thức của Lớp trừu tượng không thể private
• Phương thức trừu tượng không thể có modifier virtual
104
Lớp sealed và abstract
using System;abstract class BaseClass{ public abstract void MethodA(); public void MethodB() { Console.WriteLine ("This is the non abstract method”); }}
class DerivedClass : BaseClass{ public override void MethodA() { Console.WriteLine ("This is the abstract method overriden in derived class"); }}
105
Lớp sealed và abstract
class AbstractDemo{ public static void Main() { DerivedClass objDerived = new DerivedClass(); BaseClass objBase = objDerived; objBase.MethodA(); objDerived.MethodB(); }}
106
Lớp sealed và abstract
Lớp sealed• Là một lớp không bao giờ dùng làm lớp cơ sở
• Lớp abstract không thể được dùng như là một lớp sealed
sealed class Point {
public Point(int x, int y) {
X = x; Y = y;
} public int X; public int Y;
}
Interface
108
Định nghĩa interface
Interface cho phép tách tên của phương thức ra khỏi thực thi của phương thức
Interface chỉ ra làm thế nào phương thức được dùng chứ không phải làm thế nào phương thức được thực thi
109
Định nghĩa interface
110
Định nghĩa interface
Interface cho phép chúng định nghĩa các hành vi hay khả năng và áp dụng cho các lớp
Interface là một lớp trừu tượng thuần túy
Chỉ chứa phương thức trừu tượng không có phần implement
111
Định nghĩa interface
Cú pháp
Giới hạn• Không thể tạo instance của Interface • Không có field trong interface• Không có constructor và destructor• Không được viết access modifier• Không có kiểu lồng nhau• Không được thừa kế interface từ struct hay class
Interface có thể chứa các phương thức: Bao gồm property/indexer, event
interface Name { // Members}
112
Cài đặt interface
Một lớp có thể cài đặt một hay nhiều interface Khi một lớp cài đặt interface phải cài đặt mọi
phương thức trong interface đó Các phương thức phải có modifier là public
Cú pháp class ClassName: InterfaceName{ // Members}
113
Ví dụ
public interface IFile{ int delFile(); void disFile();}public class MyFile : IFile{ public int delFile() { System.Console.WriteLine ("DelFile Implementation!"); return(0); } public void disFile() { System.Console.WriteLine ("DisFile Implementation!"); }}
114
Ví dụ
class InterfaceDemo{ public static void Main() { MyFile objMyFile = new MyFile(); objMyFile.disFile(); int retValue = objMyFile.delFile(); }}
115
Phương thức “sealed”
Từ khóa sealed chỉ ra phương thức không được override trong lớp con của nó
class X{
public void method1(){ }virtual public void method2(){ }
}
class Y : X{
sealed override public void method2(){ }
}
class Z : Y{
override public void method2() { }}
116
Đa thừa kế interface
C# cho phép hiện thực nhiều interface
public interface IFileTwo{ void applySecondInterface();}
117
Đa thừa kế interface
public class MyFile : BaseforInterface, IFile, IFileTwo{ public int delFile() { System.Console.WriteLine ("DelFile Implementation!"); return(0); } public void disFile() { System.Console.WriteLine ("DisFile Implementation!"); } public void applySecondInterface() { System.Console.WriteLine ("ApplySecondInterface Implementation!"); }}
118
Đa thừa kế interface
class MultipleInterfaces{ public static void Main() { MyFile objMyFile = new MyFile(); objMyFile.disFile(); int retValue = objMyFile.delFile(); objMyFile.open(); objMyFile.applySecondInterface(); }}
119
Explicit Interface
Explicit Interface được dùng khi một phương thức cùng tên trong 2 interface
public interface IFile{ int delFile(); void disFile();}public interface IFileTwo{ void applySecondInterface(); void disFile();}
120
Explicit Interface
public class MyFile : BaseforInterface, IFile, IFileTwo{... void IFile.disFile() { System.Console.WriteLine ("IFile Implementation of DisFile"); } void IFileTwo.disFile() { System.Console.WriteLine ("IFileTwo Implementation of DisFile"); }..}
121
Thừa kế interface
Một interface có thể được tạo bằng cách tổ hợp nhiều interface khác
Cú pháp tương tự thừa kế trong class
interface InterfaceName1 : IterfaceName2, InterfaceName3, …{ //More operations can be added if necessary
}
122
Abstract class vs. Interface
Abstract class Interface
Thành viên abstract cũng như không abstract
Tất cả thanh viên ngầm địn abstract
Định nghĩa lớp abstract có các thành viên abstract = định nghĩa interface
Lớp abstract có thể có các phần protected, phương thức…
Thành viên của interface là public không có implementation
Chỉ được thừa kế từ 1 lớp abstract
Một lớp có thể thừa kế từ 1 hay nhiều interfaces
Lớp Abstract có thể thêm nhiều chức năng mà không phá hủy các lớp con
Tạo thêm chức năng sẽ ảnh hưởng đến lớp con
123
Interface chỉ ra tên của phương thức Virtual là implement đầu tiên của phương
thức Override là implement khác của phương thức Sealed là implement cuối cùng của phương
thức
Property – Mảng – Indexer
125
So sánh Field và Phương thức
struct ScreenPosition {
public ScreenPosition(int x, int y) {
X = rangeCheckedX(x); Y = rangeCheckedY(y);
} public int X; public int Y; private static int rangeCheckedX(int x) {
if (x < 0 || x > 600) { Console.WriteLine(“X”); } return x;
} private static int rangeCheckedY(int y) {
if (y < 0 || y > 800) { Console.WriteLine(“X”); }return y;
} }
Bad idea
ScreenPosition topLeft = new ScreenPosition(65, 45); ⋮ int x = topLeft.X; topLeft.Y = 810; // !!!!!
126
So sánh Field và Phương thức
Good ideal struct ScreenPosition {
⋮public int GetX() {
return x; } public void SetX(int newX) {
x = rangeCheckedX(newX); }
⋮private static int rangeCheckedX(int x) { ... } private static int rangeCheckedY(int y) { ... } private int x, y;
}
int x = topLeft.GetX(); topLeft.SetX(x + 10);
Dùng Field:
rõ ràng
Ngắn gọn
Dễ hiểu
127
Định nghĩa property
Properties cho phép lập trình viên truy cập các field tự nhiên hơn thay cho việc sử dụng phương thức
Cú pháp <access_modifier> <return_type> <property_name>{
get{…}
set{…}
}
128
Định nghĩa property
struct ScreenPosition{
public ScreenPosition(int X, int Y) {
x = rangeCheckedX(X); y = rangeCheckedY(Y);
} public int X {
get { return x; } set { x = rangeCheckedX(value); }
} public int Y {
get { return y; } set { y = rangeCheckedY(value); }
} private static int rangeCheckedX(int x) { ... } private static int rangeCheckedY(int y) { ... } private int x, y;
}
ScreenPosition topLeft = new ScreenPosition(65, 45); ⋮ int x = topLeft.X; topLeft.Y = 810;
129
Ví dụ property
public class Employee{ private String sName private String internal_sId public string sId { get { return internal_sId; } set { sId = internal_sId } }}
130
Ví dụ property
. .
Employee emp = new Employee();emp.sId = ”S001”;Console.WriteLine("The student id is {0}”, emp.sId);
. . .
131
Các loại property
Public Properties: Users có thể truy cập property không bị giới hạn nào
Private Properties: Users được truy cập trong lớp hay cấu trúc
Read / Write Property: Cung cấp cả read access và write access đến dữ liệu thành viên
Read - Only Property: Cung cấp read access đến dữ liệu thành viên
Write - Only Property: Cung cấp write access đến dữ liệu thành viên
132
Ví dụ property
public class Employee{ private int empsalary = 15000; //Field public int EmpSalary //Property { get { return empsalary; } }}class EmployeeTest{
133
Ví dụ property
static void Main() { Employee objEmployee = new Employee(); System.Console.WriteLine ("The salary of the Employee is {0}", objEmployee.EmpSalary); objEmployee.EmpSalary = 25000; //error }}
134
Properties Vs Fields
Properties là logical fields
Properties là mở rộng của fields
Không giống fields, properties không có lưu trực tiếp dữ liệu
135
Các giới hạn của Property
Properties không phải là field• Không thể khởi tạo property của struct thông qua set
accessorví dụ: ScreenPosition location;
location.X = 40;
• Không thể dùng property làm tham số ref, outví dụ: Method(ref topLeft.X);
• Không thể khai báo nhiều property trên 1 câu lệnhví dụ: public int X, Y { get { ... } set { ... } }
• Không thể khai báo constant hay readonly propertyví dụ: const int X { get { ... } set { ... } }
136
Các giới hạn của Property
Properties không phải là phương thức • Không thể viết code trước get, set
ví dụ: public int X {
Console.WriteLine("common code"); get { ... } set { ... }
}
• Không thể khai báo property kiểu voidpublic void X { get { ... } set { ... } }
137
Mảng
Mảng:• Tất cả các phần tử trong mảng cùng kiểu
• Các phần tử trong mảng được cấp phát liên tục
Phân loại• Mảng một chiều
• Mảng nhiều chiều
• Mảng Zich Zắc– Là mảng mà mỗi phần tử của nó là 1 mảng.– Mỗi phần tử của mảng có thể có kích thước khác nhau
• Mảng hỗn hợp
138
Khai báo Mảng
Cú pháp: mảng 1 hay nhiều chiều
Trong đó• Dimension: số chiều được bao quanh trong
ngoặc vuông. Nếu có nhiều chiều toán tử dấu phẩy được dùng ngăn cách các chiều
Chú ý:• Không chỉ ra kích thước mảng khi khai báo• Đặt [ ] trước tên biến
DataType[dimension] ArrayName;
139
Khai báo mảng
Mảng 1 chiều• type [] arrayName;
Mảng nhiều chiều• type [,] arrayName;• type [,,] arrayName;
Mảng zich zắc • type[][] arrayName;
Mảng hỗn hợp• type[][,,][,] arrayName;
140
Tạo Mảng
Mảng là kiểu tham chiếu, một biến mảng tham chiếu đến một instance mảng trên heap.
Tạo mảng chúng ta dùng toán tử new Để lấy chiều dài mảng chúng ta dùng thuộc
tính Length
141
Tạo Mảng
Kích thước mảng có thể được tính lúc runtime
int size = int.Parse(Console.ReadLine()); int[] pins = new int[size];
142
Tạo Mảng
Mảng 1 chiều• arrayName=new type[num];• type [] arrayName = new type[num];
Mảng nhiều chiều• arrayName = new type[num1, num2];• type [,] arrayName = new type[num1, num2];
Mảng zich zắc • type[][] arrayName = new type[num][];
for (int x =0; x<arrayName.Length; x++)arrayName[x] = new type[x];
143
Khởi tạo Mảng
Mảng 1 chiều• type [] arrayName = new type[num] {v1, v2, …, vnum};• type [] arrayName = new type[] {v1, v2, …, vnum};• type [] arrayName = {v1, v2, …, vnum};
Mảng nhiều chiều• type [,] arrayName = new type[num1, num2] {{x1,y1},…,{xnum1, xnum2}};• type [,] arrayName = new type[] {{x1,y1},…,{xnum1, xnum2}};• type [,] arrayName = {{x1,y1},…,{xnum1, xnum2}};
Mảng zich zắc • type[][] arrayName = new type[][]{new type{v1,…vn}, new type{v1, …, vm}};• type[][] arrayName = {new type{v1,…vn}, new type{v1, …, vm}};
Chú ý: Nếu khai báo và khởi tạo mảng riêng, chúng ta phải dùng toán tử new để khởi tạo mảng
144
Mảng giá trị - Mảng tham chiếu
Mảng kiểu giá trị
Mảng đối tượng
145
Truy cập mảng
Mảng 1 chiều• arrayName[x]
Mảng nhiều chiều• arrayName[x,y]
• arrayName[x,y,z]
Mảng zich zắc • arrayName[x][y]
146
Ví dụ: mảng
Ví dụint [] arr = new int[10];for (int i=0; i<arr.Length; i++)
arr[i] = i;
Chúng ta có thể dùng vòng lặp foreach duyệt qua mảng int [] arr = new int[10];for (int i=0; i<arr.Length; i++)
arr[i] = i;foreach (int elem in arr)
Console.write(“{0} ”, elem);
147
Ví dụ: mảng
148
Ví dụ: mảng
Mảng nhiều chiềuint [,] arr1 = new int[4,5];int [,,]arr2 = new int[5,6,4];
Zich zacint[][] arr;arr = new int[5][];arr[0] = new int[6];arr[1] = new int[5];arr[2] = new int[3];arr[3] = new int[7];arr[4] = new int[5];
149
Sao chép Mảng
Mảng là kiểu tham chiếu. Khi sao chép 1 biến mảng chúng ta sẽ có 2 tham chiếu đến cùng 1 instance mảng
Nếu muốn sao chép các instance mà mảng đang tham chiếu đến chúng ta thực hiện 2 bước• Tạo một instance mảng mới
• Thiết lập các giá trị trong mảng mới như mảng gốc
150
Sao chép Mảng
Sao chép mảng là shallow copy chứ không phải deep copy
Triangle[] triangles = new Triangle[4];
151
Sao chép Mảng
Triangle[] triangles = new Triangle[4]; for (int i = 0; i != triangles.Length; i++) {
triangles[i] = new Triangle(); }
152
Sao chép Mảng
Triangle[] copy = new Triangle[triangles.Length]; for (int i = 0; i != copy.Length; i++) {
copy[i] = triangles[i]; }
153
System.Array {1}
Mảng thật ra là đối tượng, dẫn xuất từ lớp cơ sở trừu tượng System.Array
Chúng ta có thể dùng bất kỳ phương thức và thuộc tính nào System.Array có trên mảng
Thành viên Loại thành viên Ý nghĩa
Rank Readonly instance property Trả về số chiều của mảng
GetLength Instance method Trả về số phần tử trong chiều được chỉ định của mảng
Length Readonly instance property Trả về tổng số phần tử của mảng
GetLowerBound Instance method Trả về cận dưới của một chiều cho trước. Phần lớn là 0
GetUpperBound Instance method Trả về cận trên của một chiều cho trước. Phần lớn là số phần tử của chiều đó trừ 1
IsReadOnly Readonly instance property Cho biết mảng chỉ đọc hay không. Luôn luôn là false
IsSynchronized Readonly instance property Cho biết mảng truy cập an toàn thread hay không. Luôn luôn là false
SyncRoot Readonly instance property Trả về một đối tượng cho phép truy cập đồng bộ đến mảng. Luôn luôn trả về chính mảng đang dùng
IsFixedSize Readonly instance property Cho biết mảng có kích thước cố định hay không. Luôn luôn là true
GetValue Instance method Trả về giá trị của phần tử
154
System.Array {2}
Thành viên Loại thành viên Ý nghĩa
SetValue Instance method Thiết lập giá tri của phần tử
GetEnumerator Instance method Trả về một IEnumerator. Cho phép dùng câu lệnh foreach
Sort Static method Sắp xếp các phần tử trong 1 mảng, trong 2 mảng hay trong một vùng của 1 mảng. Kiểu của các phần từ phải implement IComparer interface hay phải truyền một đối tượng mà kiểu implement interface IComparer
BinarySearch Static method Tìm kiếm theo thuật toán tìm kiếm nhị phân. Phương thức này giả sử mảng đã được sắp xếp. Kiểu của các phần từ phải implement IComparer interface. Chúng ta thường dùng phương thức Sort trước khi gọi BinarySearch.
IndexOf Static method Trả về vị trí xuất hiện đầu tiên của một giá trị trong mảng 1 chiều hay trong một phần của mảng
LastIndexOf Static method Trả về vị trí xuất hiện cuối cùng của một giá trị trong mảng 1 chiều hay trong một phần của mảng
Reverse Static method Đảo thứ tự các phần tử trong mảng 1 chiều hay trong một phần của mảng
Clone Instance method Tạo một mảng mới là bản sao của mảng gốc
CopyTo Instance method Sao chép các phần từ từ một mảng sang một mảng khác
Copy Static method Sao chép một phần các phần từ sang mảng khác, thực hiện bất kỳ yêu cầu casting nào
Clear Static method Thiệt lập một vùng các phần tử thành 0 hay null
CreateInstance Static method Tạo một instance của mảng. Phương thức hiếm dùng này cho phép định nghĩa mảng động lúc thời gian chay với bất kỳ kiểu, vùng, cận
Initialize Instance method Gọi constructor mặc nhiên của các phần tử kiều giá trị (phương thức này không thực hiện nếu các phần tử là kiễu tham chiếu)
155
Định nghĩa Indexer
Indexer cho phép coi các đối tượng như là các mảng
Cú phápclass MyClass {
public <type> this [int idx] {
get { // Return giá trị} set { // thiết lập giá trị mong muốn}
} }
156
Ví dụ indexer
class IndexerExample{ public string[] stringList =new string[10]; public string this[int index] { get { return stringList[index]; }
set { stringList[index] = value.ToString(); } }}
157
Ví dụ indexer
class Test{ static void Main() { IndexerExample indexTest = new IndexerExample(); indexTest.stringList[1]="Sam"; indexTest[2]="Tom"; System.Console.WriteLine("indexTest[1] is {0}\nindexTest[2] is {1}", indexTest[1], indexTest[2]);}}
158
So sánh Indexer với Phương thức
Indexer phải có ít nhất 1 tham sốpublic bool this [ ] { ... }
Không thể thêm code ngoài get/set trong indexerpublic bool this [ int index ] {
boundsCheck(index); get { ... } set { ... }
} Indexer không thể có kiểu trả về void
public void this [ int index ] { ... }
159
So sánh Indexer với Array
Indexer không trỏ đến vị trí bộ nhớ
Indexer có thể có chỉ mục không là số nguyênpublic int this [ string name ] { ... } // ok
Indexer có thể được overloadpublic Name this [ PhoneNumber number ] { ... } public PhoneNumber this [ Name name ] { ... } // ok
Indexer không thể dùng như tham số ref, outIntBits bits; Method(ref bits[1]); // error
160
Ví dụ indexer
using System.Collections;class StrIndex{ public Hashtable studentList = new Hashtable(); public int this[string name] { get { return (int) studentList[name]; } set { studentList[name] = value; } }}
161
Ví dụ indexer
class Test{ static void Main() { StrIndex objIndex = new StrIndex(); objIndex ["Sam"] = 232676; objIndex ["Tom"] = 455464; System.Console.WriteLine ("Phone number of Sam is {0} and Phone number of Tom is {1}", objIndex ["Sam"], objIndex["Tom"]); }}
162
Ví dụ indexer
using System.Collections;class IndexerExample{ public string[] stringList = new string[10]; public string this[int index] { get { return stringList[index]; } set { stringList[index] = value.ToString(); } } public Hashtable studentList = new Hashtable();
163
Ví dụ indexer
public int this[string number] { get { return (int) studentList [number]; } set { studentList [number] = value; } }
}
164
Ví dụ indexer
class Test{ static void Main() { IndexerExample indexTest = new IndexerExample(); indexTest.stringList[1] = "Sam"; indexTest[2] = "Tom"; indexTest ["Sam"] = 232; indexTest ["Tom"] = 455; }}
165
Indexer có nhiều tham số
Nhiều tham số: indexer được truy cập như mảng nhiều chiều
...class TestMultip{ public int this[int firstP, int secondP] { //Get and Set Accessors appear here }}. . .
166
Indexer có nhiều tham số
…{ void static Main() {
TestMultip myTest = new TestMultip();int I = myTest[1,1];
}}
Struct - Enum
168
Định nghĩa Struct
Struct là một kiểu giá trị Có thể có phương thức bên trong Không thể thừa kế
Cú pháp [attributes] [modifiers] struct <structName> [: interfaces] {
[struct-body] }[;]
169
Ví dụ Struct
RGB rgb; rgb.Red = 0xFF; rgb.Green = 0xFF; rgb.Blue = 0xFF;
struct RGB {
public int Red; public int Green;
public int Blue; }
170
Ví dụ Struct
…struct structEx{ public int structDataMember; public void structMethod1() {
//structMethod1 Implementation }}…
171
Sử dụng Structs
Không phải khởi tạo struct bằng từ khóa new
Các field không được khởi tạo cho đến khi:• Dùng từ khóa new• Khởi tạo tường minh các thành viên
Các thành viên Struct có thể có các constructor, constant, field, method, property, indexer, operator, và các kiểu lồng nhau
Một giới hạn quan trọng của struct: không thể tạo constructor không tham số
172
Kiểu enum
Mặc nhiên, phần tử đầu tiên trong enum được gán giá trị 0 và các phần tử sau có giá trị tăng dần lên 1
Giá trị mặc nhiên có thể thay đổi
public enum WeekDays{
Monday=1,Tuesday=2,Wednesday=3,Thursday=4,Friday=5
}
Collections
174
Các lớp collection
Mảng là một cách để tập hợp các phần tử cùng kiểu
Các lớp collection tập hợp các phần tử của nó như các object. Kiểu của các phần tử trong lớp collection luôn luôn là object
System.Collections • Cung cấp vài lớp để tập hợp các phần tử
175
Mảng giá trị - Mảng tham chiếu
Mảng kiểu giá trị
Mảng đối tượng
Khi chèn 1 giá trị vào collection box
Khi remove 1 giá trị từ collection unbox
176
ArrayList
ArrayList là một lớp hữu dụng cho việc bố trí các phần tử trong mảng
Những giới hạn của mảng• Thay đổi lại kích thước mảng
• Xóa một phần tử khỏi mảng
• Thêm một phần tử vào mảng
177
ArrayList
ArrayList khắc phục giới hạn của mảng• Xóa một phần tử khỏi ArrayList bằng phương
thức Remove
• Thêm một phần tử vào cuối ArrayList bằng phương thức Add (resize khi cần thiết)
• Thêm một phần tử vào giữa ArrayList bằng phương thức Insert (resize khi cần thiết)
178
ArrayList
Properties Ý nghĩa
Capacity
Count
IsFixedSize
IsReadOnly
IsSynchronize
Item
SyncRoot
179
ArrayList
Methods Ý nghĩa
Add
AddRange
Clear
Contains
CopyTo
FixedSize
IndexOf
LastIndexOf
Insert
InsertAt
Remove
RemoveAt
Sort
BinarySort
Reverse
180
Queue
Queue hiện thực collection FIFO• Thêm vào queue: Enqueue
• Lấy ra khỏi queue: Dequeue
181
Stack
Stack hiện thực collection LIFO• Thêm vào stack: Push
• Lấy ra khỏi stack: Pop
182
So sánh Mảng và Collection
Mảng có khai báo kiểu của phần tử Mảng có kích thước cố định và không tự tăng
kích thước Mảng là CTDL cho phép read/write. Các lớp
collection có thể được dùng theo cách readonly
183
Tự Tạo collection
Iteration• foreach hoạt động như thế nào
• Làm thế nào dùng foreach với lớp của chúng ta
184
Tự Tạo collection
class MyCollectionClass : IEnumerable{ ... }
foreach (string s in myCollection){
Console.WriteLine("String is {0}", s);}
IEnumerator ie = (IEnumerable) myCollection;IEnumerator e = ie. GetEnumerator(); while (e.MoveNext()){
string s = (string) e.Current; Console.WriteLine("String is {0}", s);
}
185
Tự Tạo collection
public interface IEnumerable{
IEnumerator GetEnumerator();}
public interface IEnumerator{
object Current { get; }bool MoveNext();void Reset();
}
186
Tự Tạo collection
class MyCollectionClass : IEnumerable
{CollectionPart[] _parts;......public IEnumerator GetEnumerator(){}
}
187
Tự Tạo collection
class MyCollectionClass : IEnumerable
{CollectionPart[] _parts;......public IEnumerator GetEnumerator(){
return _parts.GetEnumerator()
}}
Vì _parts là System.Array, là một kiểu liệt kê nên nó có phương thức GetEumerator() trả về IEnumerator
188
Tự Tạo collection
Giải pháp : tiếp cận dựa trên mẫu• Trình biên dịch C# compiler tìm kiếm:
– GetEnumerator() trên collection– bool MoveNext() trên kiểu enumerator– Current trên kiểu enumerator
189
Tự Tạo collection
Foreach làm cho việc liệt kê dễ dàng• Nhưng enumerator khó viết
Exception
191
Errors
Các lớp .NET Framework dùng các exception để thông báo lỗi.
Nếu chúng ta muốn lập trình trong .NET chúng ta phải biết exception
Exception là giải pháp hướng đối tượng cho bắt lỗi
192
Try code và Catch exception
Ý tưởng chính của bắt ngoại lệ : tách code hiện thực luồng chính của chương trình với code bắt bắt lỗi• Dễ hiểu
Hai bước• Viết code trong khối try
• Viết một hay nhiều khối catch ngay sau khối try
193
Try code và Catch exception
try {
int lhs = System.Int32.Parse(lhsOperand.Text); int rhs = System.Int32.Parse(rhsOperand.Text); int answer = doCalculation(lhs, rhs); result.Text = answer.ToString();
} catch (System.FormatException caught) {
// Handle the exception ⋮}
194
Nhiều catch
Những lỗi khác nhau ném các loại exception khác nhau
try {
int lhs = System.Int32.Parse(lhsOperand.Text); int rhs = System.Int32.Parse(rhsOperand.Text); int answer = doCalculation(lhs, rhs); result.Text = answer.ToString();
} catch (System.FormatException caught) { //... } catch (System.DivideByZeroException caught) { //... }
195
Viết catch tổng quát
Nếu chúng ta không muốn viết từng loại catch cho từng exception khác nhau chúng ta có thể viết một catch bắt mọi exception
try { int lhs = System.Int32.Parse(lhsOperand.Text); int rhs = System.Int32.Parse(rhsOperand.Text); int answer = doCalculation(lhs, rhs); result.Text = answer.ToString();
} catch (System.Exception caught) // this is the general catch handler { //... }
196
Viết catch tổng quát
Chú ý• Nếu có nhiều catch phù hợp với lỗi thì catch
nào gần try nhất sẽ được sử dụng
• Không nên đặt catch tổng quát lên trên những catch khác
197
Kiểm tra tràn số học
Câu lệnh checked: tất cả phép toán số học trên số nguyên được kiểm tra tràn số - OverflowException
int number = System.Int32.MaxValue; checked {
int willThrow = number++; Console.WriteLine("this won’t be reached");
}
int number = System.Int32.MaxValue; unchecked {
int willThrow = number++; Console.WriteLine("this won’t be reached");
}
198
Biểu thức checked
Chúng ta cũng có thể dùng từ khóa checked và unchecked để kiểm tra tràn số học trên biểu thức
int wontThrow = unchecked(System.Int32.MaxValue + 1); int willThrow = checked(System.Int32.MaxValue + 1);
199
Ném ngoại lệ
Câu lệnh ném ngoại lệ gồm 2 phần• Từ khóa throw
• Đối tượng được ném
throw new System.ArgumentOutOfRangeException("Bad month");
200
Khối finally
Khối finally đảm bảo những câu lệnh trong khối đó luôn luôn chạy cho dù có exception xảy ra hay không
Khối finally được đặt ngay sau khối try hay ngay sau khối catch
201
Khối finally
TextReader reader = null; try {
reader = src.OpenText(); string line; while ((line = reader.ReadLine()) != null) {
source.Text += line + "\n"; }
} finally {
if (reader != null) {
reader.Close(); }
}
Delegates
Events