9/25/2018
Lập trình Ứng dụng quản lý
C#.NET cơ bản
Lập trình hướng đối tượng
Nội dung
Class và thừa kế
Interface và Struct
Phân cấp dữ liệu trong .NET
Truyền tham số trong C#
1
9/25/2018
Nội dung
Class và thừa kế
Interface và Struct
Phân cấp dữ liệu trong .NET
Truyền tham số trong C#
Trừu tượng hóa dữ liệu
Trừu tượng hóa dữ liệu là một phương pháp tích
hợp các dữ liệu cơ sở hoặc kiểu dữ liệu có sẵn
nhằm mơ tả, biểu diễn một khái niệm hay một đối
tượng trong thế giới thực.
Ví dụ biểu diễn dữ liệu thông tin một Sinh viên,
một Nhân viên.
2
9/25/2018
Class
Cú pháp khai báo trong C#
[accessmodifier] class ClassName
{
[accessmodifier] [datatype] fieldName;
...
[accessmodifier] methodName(parameters);
}
Thành phần trong class
Thành phần dữ liệu: fields, constants
Thành phần xử lý: methods
Thành phần
Thành phần instance (thể hiện) và static (tĩnh)
Tùy theo dữ liệu hay xử lý là chung hay riêng cho mỗi
instance.
Từ khóa: static
class ClassName
{
datatype fieldInstance;
static datatype fieldStatic;
datatype methodInstance(params)
{
...
}
static datatype methodStatic(params)
{
...
}
}
3
9/25/2018
Kế thừa
Cú pháp
class ClassName : ClassBase
{
...
}
Trong C# chỉ cho phép kế thừa public.
Trong C# chỉ cho phép đơn thừa kế.
Trong C# một lớp bắt buột phải thừa kế từ một lớp
nào đó. ???
Đa hình
Cú pháp
class ClassBase
{
public virtual datatype methodVirtual()
{
...
}
}
class ClassName : ClassBase
{
public override datatype methodVirtual()
{
return base.methodVirtual();
}
}
4
9/25/2018
Abstract
C# cho phép cả class và phương thức có thể khai
báo abstract.
Một class abstract khơng có instance và một
phương thức abstract phải được overriden trong
bất kỳ lớp dẫn xuất không abstract nào.
Một phương thức abstract sẽ tự động được khai
báo virtual.
Nếu một lớp có phương thức abstract thì nó cũng
là lớp abstract.
Sealed
C# cho phép các class và phương thức được khai
báo sealed.
Một class sealed thì khơng cho phép kế thừa.
Một phương thức sealed thì khơng cho phép
overriden.
sealed class ClassBase
{
...
}
class ClassName
{
public sealed datatype method()
{
...
}
}
5
9/25/2018
Construction
Constructor
class ClassName
{
public ClassName()
{
...
}
}
Các contructor theo cùng luật overloading như
các phương thức khác.
Constructor mặc định có thể khơng cần cài đặt.
Static Constructor
class ClassName
{
public static ClassName()
{
...
}
}
Constructor static để khởi tạo các thành phần
static. Constructor static khơng có bổ từ tầm vực
truy xuất, khơng có bất kỳ một tham số nào và chỉ
có duy nhất một constructor static trong một lớp.
6
9/25/2018
Constructor gọi constructor khác
class ClassName
{
field1;
field2;
public ClassName()
{
field1 = default1;
}
class ClassName
{
field1;
field2;
public ClassName()
{
field1 = default1;
}
public ClassName(info1)
{
field1 = default1;
field2 = info1;
}
}
public ClassName(info1)
: this()
{
field2 = info1;
}
}
Constructor trong kế thừa
class ClassBase
{
field1;
public ClassBase(info1)
{
field1 = info1;
}
}
class ClassName : ClassBase
{
public ClassName(info1)
: base(info1)
{
}
}
7
9/25/2018
Disposal
Mọi vùng nhớ cấp phát cho đối tượng trong .NET
đều được bộ thu gom rác (garbage collection)
quản lý.
C# hỗ trợ mẫu Destruction để giải quyết vấn đề
cần giải phóng sớm các tài nguyên chiếm nhiều
bộ nhớ hoặc các tài ngun có vùng nhớ khơng
được quản lý (unsafe). Gồm 2 giai đoạn
Thực thi giao diện Dispose giải phóng tài nguyên
sớm.
Cài đặt Destructor để giải phóng vùng nhớ khơng
được quản lý.
Ví dụ
class ClassName : IDisposable
{
fieldLargeMem;
fieldUnsafe;
public void Dispose()
{
giải phóng fieldLargeMem
}
~ClassName()
{
giải phóng fieldUnsafe
}
}
8
9/25/2018
Phân biệt Close và Dispose
class ClassName : IDisposable
{
fieldLargeMem;
public void Dispose()
{
giải phóng fieldLargeMem
}
public void Close()
{
...
}
}
Class Object
System.Object là class cơ sở cao nhất trong cây
thừa kế các kiểu dữ liệu của .NET.
Nếu class không được khai báo tường minh thừa
kế bất kỳ class nào thì mặc định kế thừa Object.
Một số phương thức được định nghĩa trong
Object:
Phương thức
Đặc tính
Chức năng
string ToString()
public virtual
Trả về một chuỗi mô tả của đối
tượng
int GetHashTable()
public virtual
Được sử dụng trong dictionary
9
9/25/2018
Class Object (tt)
Phương thức
Đặc tính
Chức năng
bool Equals(object obj) public virtual
So sánh các thực thể của đối
tượng
bool Equals(object
objA, object objB)
public static
So sánh các thực thể của đối
tượng
bool
ReferenceEquals(obje
ct objA, object objB)
public static
So sánh hai sự tham chiếu đến
một đối tượng
Type GetType()
Public
Trả về chi tiết kiểu của một đối
tượng
object
MemberwiseClone()
Protected
tạo ra một bản copy của đối
tượng
void Finalize()
Protected
virtual
Đây là một dạng Destructor
của .Net
Property
Giúp truy suất an toàn thành phần dữ liệu của đối
tượng.
class ClassName
{
datatype field;
public datatype Field
{
get
{
return field;
}
set
{
field = value;
}
}
}
10
9/25/2018
Property (tt)
Bản chất của property là method.
Property chỉ đọc (readonly) hay chỉ ghi
(writeonly).???
Property có thể được cài đặt virtual hay
abstract.
Indexer
class ClassI
{
string[] arrData;
public string this[int i]
{
get
{
return arrData[i];
}
set
{
arrData[i] = value;
}
}
}
11
9/25/2018
Nội dung
Class và thừa kế
Interface và Struct
Phân cấp dữ liệu trong .NET
Truyền tham số trong C#
Interface
C# hỗ trợ interface (giao diện) để thực thi đa
thừa kế. ???
Một interface thì khơng có constructor hay
field.
Các thành phần trong interface mặc định là
public và không cho phép tầm vực truy suất
khác.
Các thành phần trong interface không được
phép khai báo virtual hay static.
12
9/25/2018
Ví dụ
interface ITest1
{
void func1();
void func2(int i);
}
interface ITest2
{
int func1();
}
class CTest : ITest1, ITest2
{
public void func1()
{
...
}
public void func2(int t)
{
...
}
int ITest2.func1()
{
...
}
}
Struct
Cú pháp
[accessmodifier] struct structName
{
[accessmodifier] datatype fieldName;
[accessmodifier] datatype methodName()
{
...
}
}
Struct là value type.
Struct không hỗ trợ kế thừa.
Không được phép cài đặt constructor mặc định.
Tầm vực truy suất mặc định là public.
13
9/25/2018
Nội dung
Class và thừa kế
Interface và Struct
Phân cấp dữ liệu trong .NET
Truyền tham số trong C#
Phân cấp kiểu dữ liệu trong .NET
14
9/25/2018
Phân cấp kiểu dữ liệu trong .NET (tt)
Bất kỳ kiểu dữ liệu nào cũng được dẫn xuất từ
Object, được định nghĩa tập các phương thức
thông dụng cho tất cả các kiểu (như: ToString(),
Equals(), GetHashCode(),...).
Các kiểu dữ liệu số (numerical) dẫn xuất từ
System.ValueType (tự động cấp phát trên
stack).
Kiểu dữ liệu số có các giá trị mặc định tương ứng
(như MaxValue, MinValue,...)
Các kiểu dữ liệu số có phương thức hỗ trợ lấy giá
trị (value) từ chuỗi (string) đó là Parse() và
TryParse().
Implicitly Typed Local Variables
Từ C# 3.0 cho phép khai báo biến với kiểu dữ
liệu không tường minh bằng từ khóa var. Thực
chất compiler sẽ tự gán kiểu giá trị thích hợp cho
biến.
var myInt = 0;
var myBool = true;
var myString = "Time, marches on...";
Giới hạn: chỉ sử dụng cho biến cục bộ trong
method hoặc property. Phải gán giá trị khởi tạo
(≠ null) cho biến.
15
9/25/2018
Nội dung
Class và thừa kế
Interface và Struct
Phân cấp dữ liệu trong .NET
Truyền tham số trong C#
Truyền tham số cho phương thức
Dạng tham số
Ý nghĩa
Không kèm theo từ khóa bổ trợ
Tham số được truyền bằng giá trị
(value), nghĩa là phương thức được
gọi nhận một bản sao của dữ liệu
gốc
Đi kèm từ khóa out
Tham số phải được gán giá trị bởi
phương thức được gọi nhận tham
số.
Đi kèm từ khóa ref
Tham số có thể được gán lại giá trị
trong phương thức và điều này là
không bắt buộc
Đi kèm từ khóa params
Cho phép truyền biến thiên về số
lượng tham số với cách khai báo
như là 1 tham số
16
9/25/2018
Ví dụ truyền tham số thơng thường
static int Add(int x, int y)
{
int ans = x + y;
x = 10000;
y = 88888;
return ans;
}
static void Main(string[] args)
{
int x = 9, y = 10;
Console.WriteLine("Before call: X: {0}, Y: {1}", x, y);
Console.WriteLine("Answer is: {0}", Add(x, y));
Console.WriteLine("After call: X: {0}, Y: {1}", x, y);
}
Before call: X: 9, Y: 10
Answer is: 19
After call: X: 9, Y: 10
Ví dụ truyền tham số với out
static void Add(int x, int y, out int ans)
{
ans = x + y;
}
static void Main(string[] args)
{
int ans;
Add(90, 90, out ans);
Console.WriteLine("90 + 90 = {0}", ans);
}
static void ThisWontCompile(out int a)
{
Console.WriteLine("Error! Forgot to assign output
arg!");
}
17
9/25/2018
Ví dụ truyền tham số với ref
static void SwapStrings(ref string s1, ref string s2)
{
string tempStr = s1;
s1 = s2;
s2 = tempStr;
}
static void Main(string[] args)
{
string str1 = "Flip";
string str2 = "Flop";
Console.WriteLine("Before: {0}, {1} ", str1, str2);
SwapStrings(ref str1, ref str2);
Console.WriteLine("After: {0}, {1} ", str1, str2);
}
Before: Flip, Flop
After: Flop, Flip
Ví dụ truyền tham số với params
static double CalculateAverage(params double[] values)
{
Console.WriteLine("You sent me {0} doubles.",
values.Length);
double sum = 0;
if (values.Length == 0)
return sum;
for (int i = 0; i < values.Length; i++)
sum += values[i];
return (sum / values.Length);
}
18
9/25/2018
Ví dụ truyền tham số với params (tt)
static void Main(string[] args)
{
double average;
average = CalculateAverage(4.0, 3.2, 5.7, 64.22, 87.2);
Console.WriteLine("Average of data is: {0}", average);
double[] data = { 4.0, 3.2, 5.7 };
average = CalculateAverage(data);
Console.WriteLine("Average of data is: {0}", average);
Console.WriteLine("Average of data is: {0}",
CalculateAverage());
}
You sent me 5 doubles.
Average of data is: 32.864
You sent me 3 doubles.
Average of data is: 4.3
You sent me 0 doubles.
Average of data is: 0
Phân biệt kiểu tham số và kiểu dữ liệu
struct STest
{
public int X, Y;
}
class CTest
{
public int X, Y;
}
static void Func1(STest s, CTest c)
{
s.X = c.X = 10;
}
static void Func2(ref STest s, ref CTest c)
{
s.X = c.X = 10;
}
19
9/25/2018
Phân biệt kiểu tham số và kiểu dữ liệu (tt)
static void Main(string[] args)
{
var s = new STest();
var c = new CTest();
Console.WriteLine("s.X= {0}, c.X= {1}", s.X, c.X);
Func1(s, c);
Console.WriteLine("Sau Func1: s.X= {0}, c.X= {1}", s.X, c.X);
Func2(ref s, ref c);
Console.WriteLine("Sau Func2: s.X= {0}, c.X= {1}", s.X, c.X);
}
s.X= 0, c.X= 0
Sau Func1: s.X= 0, c.X= 10
Sau Func2: s.X= 10, c.X= 10
Phân biệt kiểu tham số và kiểu dữ liệu (tt)
static void
{
s = new
c = new
}
static void
{
s = new
c = new
}
Func3(STest s, CTest c)
STest() { X = 1 };
CTest() { X = 1 };
Func4(ref STest s, ref CTest c)
STest() { X = 1 };
CTest() { X = 1 };
static void Main(string[] args)
{
var s = new STest();
var c = new CTest();
Console.WriteLine("s.X= {0}, c.X= {1}", s.X, c.X);
Func3(s, c);
Console.WriteLine("Sau Func3: s.X= {0}, c.X= {1}", s.X, c.X);
Func4(ref s, ref c);
Console.WriteLine("Sau Func4: s.X= {0}, c.X= {1}", s.X, c.X);
}
20