Tải bản đầy đủ (.pdf) (68 trang)

C cơ bản đến nâng cao

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (822.57 KB, 68 trang )

1.Biến và hằng
C# phân biệt chữ hoa và chữ thường
Các kiểu dữ liệu cơ bản của biến:
Int: số nguyên có dấu 4byte
Short: số nguyên có dấu 2 byte
Long: số nguyên có dấu 8byte
Char: kí tự Unicode 2byte
Bool:giá trị logic True/False 1byte
Float: số thực dấu phẩy động 4byte
Double: số thực dấu phẩy động 8byte
1.1 Khai báo
<kiểu dữ liệu> <tên biến> ;
Const <kiểu dữ liệu> <tên hằng>=<giá trị của hằng>;
Khai báo hằng kiểu liệt kê:
[thuộc tính] [bổ sung] enum <tên liệt kê> [:kiểu cơ sở] {danh sách các thành phần
liệt kê};
enum NhietDoNuoc :int
{
DoDong =0,
DoNguoi= 20,
DoAm = 40,
DoNong = 60,
DoSoi = 100,
}
1.2 Chú ý
Để dùng được biến thì bắt buộc phải gán giá trị cho biến trước khi có một lệnh tham
chiếu đến nó.
2.Các câu lệnh
2.1 Các câu lệnh điều khiển
a. if……else
if (biểu thức điều kiện)


{<các câu lệnh>}
else
{<các câu lệnh>}
Chú ý: phần else có thể có hoặc không
b. switch
switch ( biểu thức điều kiện)
{
case <giá trị 1>: <các câu lệnh>
<lệnh nhảy> //có thể là break,goto
case <giá trị 2>: <các câu lệnh>
<lệnh nhảy> //có thể là break,goto
…………………………….
case <giá trị n>: <các câu lệnh>
<lệnh nhảy> //có thể là break,goto
default:<các câu lệnh>
}
Khi lệnh switch được thực hiện thì giá trị trong biểu thức điều kiện được tính, nếu giá
trị nào sau case bằng với giá trị trong biểu thức điều kiện thì câu lệnh sau case được
thực hiện và sau mỗi case nên có lệnh nhảy (break,goto) để thoát ra khỏi câu lệnh
switch vì nếu không cả những lệnh từ case đó trở đi đều được thực hiện.
Nếu không có giá trị nào sau case bằng với biểu thức điều kiện thì câu lệnh sau default
được thực hiên, default có thể có hoặc không.
2.2 Câu lệnh lặp
a. goto
-Lệnh goto giúp ta nhảy vô điều kiện tới một vị trí bất kì trong chương trình thông qua
nhãn. Tuy nhiên ta hạn chế dùng goto vì chương trình rối, mất đi tính cấu trúc
<tên nhãn> : <các câu lệnh … >
………………….
goto <tên nhãn>;
b. while

while (biểu thức)
{
<các câu lệnh thực hiện>
}
Khi vòng lặp while được thực hiện, biểu thức được tính toán và giá trị trả về phải là giá
trị kiểu bool (true/false). Nếu biểu thức là true thì các câu lệnh sẽ được thực hiện, khi
thức hiện xong thì giá trị biểu thức lại được tính lại và vòng lặp mới bắt đầu, vòng lặp chỉ
dừng lại khi biểu thức trả về false.
c. do….while
do
{
<câu lệnh thực hiên>
}while (biểu thức)
Nguyên tắc cũng giống như while nhưng ở đây, các câu lệnh đươc thực hiện trước sau đó
biểu thức mới được tính toán xem có thực hiện vòng lặp tiếp theo hay không tức là dù
hoàn cảnh nào thì các lệnh trong do while cũng được thực hiện ít nhất một lần.
d. for
for ([phần khởi tạo];[biểu thức điều kiện];[bước lặp])
{
<các câu lệnh>
}
Chú ý: [ ] có thể có hoặc không
e. foreach
for(<kiểu tập hợp> <tên truy cập thành phần> in <tên tập hợp>)
{ <các câu lệnh> }
Vòng lắp foreach cho phép tạo vòng lặp thông qua 1 tập hợp hay 1 mảng. Khi thực hiện
vòng lặp sẽ duyệt qua tất cả các thành phần của tập hơp theo thứ tự sắp xếp. Duyệt đến
phần tử cuối vòng lặp tự động thoát ra ngoài
VD:
using System;

public class UsingForeach
{
public static int Main()
{
int[] intArray={1,2,3,4,5,6,7,8,9,10};
foreach(int item in intArray)
{
Console.Write(“{0}”,item);
}
return 0;
}
}
KQ: màn hình sẽ in ra: 1 2 3 4 5 6 7 8 9 10
f. break và continue
break: thoát khỏi vòng lặp và thực hiện các lệnh phía sau vòng lặp
continue: ngừng thực hiện các công việc còn lại của vòng lặp hiện tại và quay về đầu
vòng lặp thực hiện vòng lặp tiếp theo.
3.Các toán tử
3.1 Toán tử toán học
-Các phép toán số học cơ bản: +,-,*, /
-Phép toán chia lấy dư: %
3.2 Các toán tử tăng giảm
+=, -+, *=, /=, %=
3.2 Toán tử quan hệ
==, !=, >, >=,<, <=
3.3 Toán tử logic
&&, ||, !
3.5 Phép toán logic
&, |, ^
3.6 Toán tử ba ngôi

<biểu thức điều kiện>? <biểu thức1>:<biểu thức 2>;
4. namespace
5. Mảng
5.1 Khai báo và từ khóa params
<kiểu dữ liệu>[] <tên mảng> = new <kiểu dữ liệu>[kích thước];// khai báo và tạo luôn
thể hiện cho mảng
Hoặc
Var[] <tên mảng>=new <kiểu dữ liệu>[kích thước];
-Mảng là kiểu dữ liệu tham chiếu

namespace Programming_CSharp
{
using System;
// tạo một lớp đơn giản để lưu trữ trong mảng
public class Employee
{
// bộ khởi tạo lấy một thamsố
public Employee( int empID )
{
this.empID =empID;
}
public override string ToString()
{
return empID.ToString();
}
// biến thành viên private
private int empID;
private int size;
}
public class Tester

{
static void Main()
{
int[] intArray;
Employee[] empArray;
intArray = new int[5];
empArray =new Employee[3];
// tạo đối tượng đưa v{o mảng
for( int i = 0; i < empArray.Length; i++)
{
empArray[i] =new Employee(i+5);
}
// xuất mảng nguyên
for( int i = 0; i < intArray.Length; i++)
{
Console.Write(intArray[i].ToString()+"\t");
}
// xuất mảng Employee
for( int i = 0; i < empArray.Length; i++)
{
Console.WriteLine(empArray[i].ToString()+"\t");
}
Console.ReadKey();
}
}
}



VD: về cách sử dụng từ khóa params, params cho phép ta truyền tham số cho một hàm(

phương thức) khi ra không biết phải truyền bao nhiêu phần tử, ta có thể truyền 1 mảng
hoặc 1 tập hợp các phần tử và hàm sẽ tự động gom chúng lại và coi nó như là 1 mảng ở
trong hàm đó.
namespace Programming_CSharp
{
using System;
public class Tester
{
public void DisplayVals(params int[] intVals)
{
foreach (int i in intVals)
{
Console.WriteLine("DisplayVals {0}", i);
}
}
static void Main()
{
Tester t = new Tester();
t.DisplayVals(5,6,7,8);
int[] explicitArray = new int[5] {1,2,3,4,5};
t.DisplayVals(explicitArray);
Console.ReadKey();
}
}
}

5.2 Khởi tạo giá trị
Vd:
Int[] a=new int[5] {1,2,3,4,5};
Hoặc

Int[] a={1,2,3,4,5};
Hoặc
a[0]=1;
……………
5.3 Mảng đa chiều
Vd: mảng 2 chiều như sau
Int[,] a=new int[3,4]; // mảng 2 chiều gồm 3 hàng và 4 cột
namespace Programming_CSharp
{
using System;
public class Tester
{
static void Main()
{
// khai báo số dòng và sốcộtcủa mảng
const int rows = 4;
const int columns = 3;
// khai báo mảng 4x3 số nguyên
int[,] rectangularArray = new int[rows, columns];
// khởi tạo các thành phần trong mảng
for(int i= 0; i< rows; i++)
{
for(int j= 0; j< columns; j++)
{
rectangularArray[i,j] = i+j;
}
}
// xuất nội dung ra màn hình
for(int i= 0; i< rows; i++)
{

for(int j= 0; j< columns; j++)
{
Console.WriteLine("rectangularArray[{0},{1}] = {2}",i, j, rectangularArray[i, j]);
}
}
Console.ReadKey();
}
}
}

5.4 Mảng lởm chởm
Int[][] a=new int[3][];
a[0]=new int[2]; |___|
a[1]=new int[3]; | __ |___|
a[2]=new int[1]; |___|___|___|
// khai báo mảng lởm chởm
namespace Programming_CSharp
{
using System;
public class Tester
{
static void Main()
{
const int rows = 4;
// khai báo mảng tối đa bốn dòng
int[][][] jaggedArray = new int[rows][][];
// dòng đầu tiên có 5 phần tử
jaggedArray[0] = new int[5][2];
// dòng thứ hai có2 phần tử
jaggedArray[1] = new int[2][1];

// dòng thứ ba có3 phần tử
jaggedArray[2] = new int[3];
// dòng cuối cùng có 5 phần tử
jaggedArray[3] = new int[5];
// khởi tạo một vài giá trị cho các thành phần của mảng
jaggedArray[0][3] = 15;
jaggedArray[1][1] = 12;
jaggedArray[2][1] = 9;
jaggedArray[2][2] = 99;
jaggedArray[3][0] = 10;
jaggedArray[3][1] = 11;
jaggedArray[3][2] = 12;
jaggedArray[3][3] = 13;
jaggedArray[3][4] = 14;
for (int i = 0; i < 5; i++)
{
Console.WriteLine("jaggedArray[0][{0}] = {1}", i, jaggedArray[0][i]);
}
for (int i = 0; i < 2; i++)
{
Console.WriteLine("jaggedArray[1][{0}] = {1}", i, jaggedArray[1][i]);
}
for (int i = 0; i < 3; i++)
{
Console.WriteLine("jaggedArray[2][{0}] = {1}", i, jaggedArray[2][i]);
}
for (int i = 0; i < 5; i++)
{
Console.WriteLine("jaggedArray[3][{0}] = {1}", i, jaggedArray[3][i]);
}

Console.ReadKey();
}
}
}


5.5 Mảng đối tượng
Vd:
button[] a=new button[2]; // mảng gồm 2 đối tượng là các button
5.6 Chuyển đổi mảng
namespace Programming_CSharp
{
using System;
// tạo lớp để lưu trữ trong mảng
public class Employee
{
public Employee(int empID)
{
this.empID = empID;
}
public override string ToString()
{
return empID.ToString();
}
// biến thành viên
private int empID;
private int size;
}
public class Tester
{

// phương thức này lấy một mảng các object
// chúng ta truyền vào mảng c|cđốitượng Employee
// v{ sau đó l{ mảng các string, có sự chuyển đổingầm
// vì cả hai điều dẫn xuất từ lớp object
public static void PrintArray(object[] theArray)
{
Console.WriteLine("Contentsof the Array: {0}", theArray.ToString());
// in ra từng thành phần trong mảng
foreach (object obj in theArray)
{
// trình biêndịch sẽ gọi obj.ToString()
Console.WriteLine("Value: {0}", obj.ToString());
}
}
static void Main()
{
// tạo mảng c|c đối tượng Employee
Employee[] myEmployeeArray = new Employee[3];
// khởi tạo c|c đối tượng của mảng
for (int i = 0; i < 3; i++)
{
myEmployeeArray[i] = new Employee(i + 5);
}
// hiểu thị giá trị của mảng
PrintArray(myEmployeeArray);
// tạo mảng gồmhai chuỗi
string[] array = { "hello", "world" };
// xuất ra nộidung của chuỗi
PrintArray(array);
Console.ReadKey();


}
}
}

VD2:
namespace Programming_CSharp
{
using System;
public class Tester
{
public static void PrintArray(object[] theArray)
{
foreach (object obj in theArray)
{
Console.WriteLine("Value: {0}", obj);
}
Console.WriteLine("\n");
}
static void Main()
{
string[] myArray = { "Who", "is", "Kitty", "Mun" };
PrintArray(myArray);
Array.Reverse(myArray);
PrintArray(myArray);
string[] myOtherArray = { "Chung", "toi", "la", "nhung", "nguoi", "lap",
"trinh", "may", "tinh" };
PrintArray(myOtherArray);
Array.Sort(myOtherArray);
PrintArray(myOtherArray);

Console.ReadKey();
}
}
}

5.7 Bộ chỉ mục
-Giúp ta truy cập một tập hợp bên trong 1 lớp như thể bản thân lớp là 1 mảng. ta phải
khai báo bộ chỉ mục bên trong lớp đó theo cú pháp:
<kiểu dữ liệu> this [<kiểu dữ liệu><đối mục>]
{ get; set; }
VD: Bộ chỉ muc có kiểu chỉ mục int
namespace Programming_CSharp
{
using System;
// tạo lớp ListBox
public class ListBoxTest
{
// khởi tạo ListBox với một chuỗi
public ListBoxTest(params string[] initialStrings)
{
// cấpphát không gian cho chuỗi
strings = new String[256];
// copy chuỗi truyền từ thamsố
foreach (string s in initialStrings)
{
strings[ctr++] = s;
}
}
// thêm một chuỗi
public void Add(string theString)

{
if (ctr >= strings.Length)
{
// xử lý khi chỉmục sai
}
else
strings[ctr++] = theString;
}
// thực hiện bộ chỉ m
public string this[int index]
{
get
{
if (index < 0 || index >= strings.Length)
{
// xử lý chỉmục sai
}
return strings[index];
}
set
{
// if (index >= ctr)
// {
// xử lý lỗi chỉ mục không tồn tại
/// }
// else
strings[index] = value;
if (ctr <= index) ctr = index + 1;
}
}

// lấy sốlượng chuỗiđược lưugiữ
public int GetNumEntries()
{
return ctr;
}
// các biến thành vịên lưu giữ mảng cho bộ chỉ mục
private string[] strings;
private int ctr = 0;
}
// lớp thực thi
public class Tester
{
static void Main()
{
// tạo một đối tượng ListBox mới và khởi tạo
ListBoxTest lbt = new ListBoxTest("Hello", "World");
// thêm một số chuỗi vào lbt
lbt.Add("Who");
lbt.Add("is");
lbt.Add("Ngoc");
lbt.Add("Mun");
// dùng bộ chỉmục
string strTest = "Universe";
lbt[1] =strTest;
lbt[10] = "hatran";
// truy cập và xuất tất cả các chuỗi
for (int i = 0; i < lbt.GetNumEntries(); i++)
{
Console.WriteLine("lbt[{0}]:{1}", i, lbt[i]);
}

Console.ReadKey();

}
}
}

VD: Bộ chỉ mục có kiểu chỉ mục chuỗi (string)
namespace Programming_CSharp
{
using System;
// tạo lớp List Box
public class ListBoxTest
{
// khởi tạo vớinhững chuỗi
public ListBoxTest(params string[] initialStrings)
{
// cấpphát chuỗi
strings = new String[256];
// copy các chuỗi truyền vào
foreach (string s in initialStrings)
{
strings[ctr++] = s;
}
}
// thêm một chuỗi vào cuối danh sách
public void Add(string theString)
{
strings[ctr] = theString;
ctr++;
}

// bộ chỉ mục
public string this[int index]
{
get
{
if (index < 0 || index >= strings.Length)
{
// chỉmục không hợp lệ
}
return strings[index];
}
set
{
strings[index] = value;
}
}
private int findString(string searchString)
{
for (int i = 0; i < strings.Length; i++)
{
if (strings[i].StartsWith(searchString))
{
return i;
}
}
return -1;
}
// bộ chỉ mục dùng chuỗi
public string this[string index]
{

get
{
if (index.Length == 0)
{
// xử lý khi chuỗi rỗng
}
return this[findString(index)];
}
set
{
strings[findString(index)] = value;
}
}
// lấy sốchuỗi trong mảng
public int GetNumEntries()
{
return ctr;
}
// biến th{nh viên lưu giữ mảng các chuỗi
private string[] strings;
// biến th{nh viên lưu giữa số chuỗi trong mảng
private int ctr = 0;
}
public class Tester
{
static void Main()
{
// tạo đối tượng List Boxv{ sau đó khởi tạo
ListBoxTest lbt = new ListBoxTest("Hello", "World");
// thêm các chuỗi vào

lbt.Add("Who");
lbt.Add("is");
lbt.Add("Ngoc");
lbt.Add("Mun");
// truy cập bộ chỉ mục
string str = "Universe";
lbt[1] = str;
lbt["Hel"] = "Hi";
//lbt[“xyzt”] = “error!”;
// lấy tất cả cácchuỗi ra
for (int i = 0; i < lbt.GetNumEntries(); i++)
{
Console.WriteLine("lbt[{0}] = {1}", i, lbt[i]);
}
Console.ReadKey();
}
}
}
5.7 Mảng động List và ArrayList
1. List
Danh sách có kiểu có nghĩa là chúng ta biết trước được kiểu dữ liệu mà mình đưa vào
List<> để tạo thành 1 danh sách với kiểu dữ liệu mà chúng ta đưa vào.
- Cấu tạo của List là dạng Template do đó nếu bạn nào đã từng tìm hiểu qua chắc hẳn sẽ
rất dể tiếp cận với List.
- Khai báo và Khởi tạo List :
// Khoi tao List kiểu int
List<int> intList = new List<int>();
// Khoi tao va them gia tri ban dau
List<string> StrList = new List<string>()
{

"Pham Phuong Nguyen",
"Microsoft Student Partner",
"I Love Technology"
};
- Về mặt truy suất chúng ta có thể dùng vòng lập để truy suất từng phần tử, thông thường
là dùng for hay foreach
- Việc truy suất giá trị các phần tử trong List rất dể dàng, giống hệt như trong mảng tỉnh,
chúng ta chỉ cần chỉ định chỉ số mảng là đã có thể truy suất :
Ví dụ :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ListAndDictionarySample
{
class Program
{
static void Main()
{
List<string> StrList = new List<string>()
{
"Pham Phuong Nguyen",
"Microsoft Student Partner",
"HCM Open University",
""
};
for (int i = 0; i < StrList.Count; i++)
{
Console.WriteLine(StrList[i]);

}
string University = StrList[2];
// Thay đổi giá trị các phần tử của mảng
StrList[0] = "Lệnh Hồ Xung";
StrList[1] = "Hoa Sơn Kiếm Khách";
StrList[2] = "Núi Hoa Sơn";
StrList[3] = "";
for (int i = 0; i < StrList.Count; i++)
{
Console.WriteLine(StrList[i]);
}
Console.WriteLine("{0}",University);
Console.ReadKey();
}
}
}
2. ArrayList
- Danh sách không có kiểu chúng ta có thể hiểu một cách nom na, mặc dù đây là mảng
động nhưng chứa bên trong nó không phải là 1 kiểu dữ liệu xác định, chúng ta có thể đưa
vào trong mảng từng phần tử kiểu khác nhau hoàn toàn VD như bool,String,Double …
- Khai báo và Khởi tạo ArrayList :
– Với cách khai báo phía trên chúng ta dể dàng hiểu rằng trong ArrayList có thể chứa
đồng thời nhiều object (kiểu dữ liệu không có định).
- Một điều cần lưu ý khi truy suất các phần tử trong ArrayList là chúng ta phải ép
kiểu giống với kiểu của phần tử ban đầu khi đưa vào mảng, nếu không hệ thống sẽ không
hiểu :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections;

namespace ListAndDictionarySample
{
class Program
{
static void Main(string[] args)
{
ArrayList arrList = new ArrayList()
{
"Pham Phuong Nguyen",22,true,
};
String Name = arrList[0] as String;
int Ages = (int)arrList[1];
bool Smile = (bool)arrList[2];
String Info = String.Format("Name: {0} \n" + "Ages: {1} \n" +"Smile: {2}
\n", Name, Ages, Smile);
Console.WriteLine(Info);
Console.WriteLine(arrList[0]);
Console.ReadKey();
}
}
}




namespace Programming_CSharp
{
using System;

using System.Collections;
// một lớp đơn giản để lưu trữ trong mảng
public class Employee
{
public Employee(int empID)
{
this.empID = empID;
}
public override string ToString()
{
return empID.ToString();
}
public int EmpID
{
get
{
return empID;
}
set
{
empID = value;
}
}
private int empID;
}
public class Tester
{
static void Main()
{
ArrayList empArray = new ArrayList();

ArrayList intArray = new ArrayList();
// đưa v{o mảng
for (int i = 0; i < 20; i++)
{
empArray.Add(new Employee(i + 100));
intArray.Add(i * 5);
}
// in tất cả nộidung
for (int i = 0; i < intArray.Count; i++)
{
Console.Write("{0} ", intArray[i].ToString());
}
Console.WriteLine("\n");
// in tất cả nộidung của mảng
for (int i = 0; i < empArray.Count; i++)
{
Console.Write("{0} ", empArray[i].ToString());
}
Console.WriteLine("\n");
Console.WriteLine("empArray.Count: {0}", empArray.Count);
Console.WriteLine("empArray.Capacity: {0}", empArray.Capacity);
Console.ReadKey();
}
}
}

8. Giao diện tập hợp và stack,hàng đợi Hashtable
8.1 Giao diện IEnumerable và IEnumerator
Giao diện IEnumerator cung cấp khả năng lặp cho tập hợp bên trong một
class. IEnumerator yêu bạn thực hiện ba phương thức:

-Phương thức MoveNext, Reset và thuộc tính Curent
Giao diên IEnumerable cung cấp hỗ trợ vòng lặp foreach. IEnumerable đòi hỏi bạn
phải thực hiện phương thức GetEnumerator
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
Ban đầu, bạn có thể thấy khó hiểu để sử dụng các giao diện này. Giao diện IEnumerator
cung cấp vòng lặp lặp trên một tập hợp trong một class. IEnumerable cho phép liệt kê
bằng cách sử dụng vòng lặp foreach. Tuy nhiên, phương thức GetEmunerator của giao
diện IEnumerable trả về một giao diện IEnumerator. Vì vậy, để thực hiện IEnumerable,
bạn cũng phải thực hiện IEnumerator. Nếu bạn không thực hiện IEnumerator, bạn
không thể đúc giá trị trả lại từ phương thức GetEnumerator IEnumerable để các
IEnumerator giao diện.

Nói tóm lại, việc sử dụng IEnumerable yêu cầu các class thực hiện IEnumerator. Nếu
bạn muốn cung cấp hỗ trợ cho foreach, thực hiện cả hai giao diện.

namespace Programming_CSharp
{
using System;
using System.Collections;
// tạo một control đơn giản
public class ListBoxTest : IEnumerable
{
// lớp thực thi riêngListBoxEnumerator
private class ListBoxEnumerator : IEnumerator
{
public ListBoxEnumerator(ListBoxTest lbt)
{

this.lbt = lbt;
index = -1;
}
// gia tăng index v{ đảm bảo giátrị này hợp lệ
public bool MoveNext()
{
index++;
if (index >= lbt.strings.Length)
return false;
else
return true;
}
public void Reset()
{
index = -1;
}
public object Current
{
get
{
return (lbt[index]);
}
}
private ListBoxTest lbt;
private int index;
}
// trả vềEnumerator
public IEnumerator GetEnumerator()
{
return (IEnumerator)new ListBoxEnumerator(this);

}
// khởi tạo listbox với chuỗi
public ListBoxTest(params string[] initStr)
{
strings = new String[10];
// copy từ mảng chuỗi tham số
foreach (string s in initStr)
{
strings[ctr++] = s;
}
}
public void Add(string theString)
{
strings[ctr] = theString;
ctr++;
}
// cho phép truy cập giống như mảng
public string this[int index]
{
get
{
if (index < 0 || index >= strings.Length)
{
// xử lý index sai
}
return strings[index];
}
set
{
strings[index] = value;

}
}
// số chuỗinắm giữ
public int GetNumEntries()
{
return ctr;
}
private string[] strings;
private int ctr = 0;
}
public class Tester
{
static void Main()
{
ListBoxTest lbt = new ListBoxTest("Hello", "World");
lbt.Add("What");
lbt.Add("Is");
lbt.Add("The");
lbt.Add("C");
lbt.Add("Sharp");
string subst = "Universe";
lbt[1] = subst;
// truy cập tất cả các chuỗi
int count = 1;
foreach (string s in lbt)
{
Console.WriteLine("Value {0}: {1}", count, s);
count++;
}
Console.ReadKey();

}
}
}
8.2 Giao diện IComparable và Icomparer
1.Icomparable
Khi muốn sắp xếp 1 mảng kiểu int,long,float,char,string… (tức là các kiểu dữ liệu đã
định nghĩa sẵn) thì ta có thể dùng phương thức Sort(). Nhưng với đối tượng mà ta tự định
nghĩa thì ta phải chỉ rõ cách sắp xếp cho kiểu dữ liệu đó ví dụ như:
using System.Collections.Generic;
using System;
class Person
{
public int Age{get;set;}
public string Name{get;set;}
}
class Test
{
static void Main()
{
List<Person> personList = new List<Person>();
personList.Add(new Person { Age = 10, Name = "John" });
personList.Add(new Person { Age = 15, Name = "Ann" });
personList.Add(new Person { Age = 8, Name = "Kevin" });
personList.Sort(); //Lỗi ở đ}y
foreach (var item in personList)
{
Console.WriteLine(item.Name + ":" + item.Age);
}
Console.ReadKey(true);
}

}

Nhưng lúc này chúng ta không thể gọi phương thức Sort() trên personList bởi vì trình
biên dịch sẽ không hiểu là cách sắp xếp đối tượng kiểu Person này là như thế nào( sắp
xếp theo tuổi hay theo tên, sắp xếp tăng hay giảm dần).
Phương thức Sort() của List<> sẽ chỉ có thể thực hiện được trên những class có cài đặt
interface IComparable. Nói cách khác, các class này phải có một phương thức chỉ rõ
cách so sánh hai đối tượng của class đó là như thế nào. IComparable có một phương
thức duy nhất là CompareTo. Tham số nhận vào là một kiểu object hoặc trong trường hợp
bạn sử dụng interface IComparable<> thì tham số truyền vào là kiểu dữ liệu của lớp cài
đặt interface đó. Như vậy, lớp Person của chúng ta lúc này sẽ là:
class Person : IComparable
{
public int Age { get; set; }
public string Name { get; set; }
public int CompareTo(object o)
{
Person r = (Person)o;
return this.Age.CompareTo(r.Age);
}
}
Phương thức CompareTo sẽ dựa vào giá trị trả về để biết được thứ tự của hai đối tượng
khi đem ra so sánh. Giá trị trả về nhỏ hơn 0 nghĩa là đối tượng hiện tại sẽ nhỏ hơn (hay
đứng trước) đối tượng other. Giá trị trả về là 0 thì hai đối tượng bằng nhau, còn nếu giá
trị trả về lớn hơn 0 thì đối tượng hiện tại lớn hơn (hay đứng sau) đối tượng other. Ở trên,
thay vì phải dùng các câu lệnh if else để trả về giá trị theo quy định thì chúng ta đã tận
dụng lại phương thức CompareTo có sẵn trong các kiểu dữ liệu cơ bản (thuộc tính Age
thuộc kiểu Integer). Hiện tại, chúng ta đang cài đặt cho lớp Person này sẽ sắp xếp theo
thuộc tính Age. Nếu như cách so sánh phức tạp hơn, chúng ta chỉ cần cài đặt nó trong
phương thức CompareTo, miễn sao giá trị trả về phản ánh đúng thứ tự mà chúng ta yêu

cầu.
Tuy nhiên, cài đặt IComparable có một hạn chế đó là chúng ta chỉ có thể quy định cho
lớp Person này 1 cách sắp xếp duy nhất. Giả sử chúng ta muốn cùng lúc vừa có thể sắp
xếp danh sách personList theo tên, vừa có thể sắp xếp theo tuổi thì phải làm sao? Khi đó
chúng ta cần đến sự trợ giúp của một interface khác: IComparer.
namespace Programming_CSharp
{
using System;
using System.Collections;
// một lớp đơn giản để lưu trữ trong mảng
public class Employee : IComparable
{
public Employee(int age, string name)
{
this.age = age;
this.name = name;
}
public override string ToString()
{
return ( name.ToString()+":"+age.ToString());

}
public int Age
{
get
{
return age;
}
set
{

age = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
// So s|nh được delegate cho Employee
// Employee sử dụng phương thức so sánh
// mặc địnhcủa số nguyên
public int CompareTo(Object o)
{
Employee r = (Employee)o;
int ret= this.name.CompareTo(r.name); // xap sep theo ten, neu cung ten
thi xap sep theo tuoi(uu tien tuoi nho)
if (ret == 0) //luon xap xep theo bang chu cai vao
xap sep tang dan
return this.Age.CompareTo(r.age);
else
return ret;
}
private int age;
private string name;

}
public class Tester
{
static void Main()
{
ArrayList empArray = new ArrayList();
empArray.Add(new Employee(20, "Ha"));
empArray.Add(new Employee(17, "Tien"));
empArray.Add(new Employee(10, "Tien"));
empArray.Add(new Employee(25, "Tien"));
empArray.Add(new Employee(13, "Huy"));
for (int i = 0; i < empArray.Count; i++)
{
Console.Write("{0} ", empArray[i].ToString());
}
Console.WriteLine("\n");
// sắpxếp lại mảng Employee
empArray.Sort();
// hiển thị tất cả nội dung của mảng Employee
for (int i = 0; i < empArray.Count; i++)
{
Console.WriteLine("{0} ",empArray[i].ToString());
}
Console.WriteLine("\n");
Console.ReadKey();
}
}
}



2.Icomparer
Khác với IComparable được cài đặt ngay trên đối tượng mà bạn muốn sắp xếp thì
IComparer như là một bộ so sánh riêng. Khi cần sắp xếp với bộ sắp xếp nào thì ta chỉ
cần gắn nó với bộ so sánh đó là được (Hãy tưởng tượng bạn đang có 10 thùng hàng và có
2 loại máy sắp xếp, nếu cho 10 thùng hàng này qua máy 1 thì các thùng hàng sẽ được sắp
xếp theo kích thước, còn nếu cho 10 thùng hàng này qua máy 2 thì các thùng hàng sẽ
được sắp xếp theo khối lượng. Máy 1 và 2 ở đây đóng vai tròng giống như các Comparer,
mỗi máy sẽ có cách sắp xếp riêng mà khi cần sử dụng thì gọi tới nó).
Chúng ta sẽ bắt đầu với việc cài đặt một Bộ so sánh cho phép so sánh hai đối tượng kiểu
Person theo thuộc tính Age và một Bộ so sánh theo thuộc tính Name
class MyAgeComparer : IComparer
{
public int Compare(object a, object b)
{
Employee x = (Employee)a;
Employee y = (Employee)b;
int ret= x.Age.CompareTo(y.Age);
if (ret == 0)
return x.Name.CompareTo(y.Name);
else
return ret;
}


class MyNameComparer : IComparer
{
public int Compare(object c, object d)
{
Employee x = (Employee)c;
Employee y = (Employee)d;

int ret2= x.Name.CompareTo(y.Name);
if (ret2 == 0)
return x.Age.CompareTo(y.Age);
else
return ret2;
}
}

Đã có hai Comparer như trên, khi chúng ta muốn sử dụng bộ so sánh nào khi sắp xếp với
phương thức Sort thì chỉ việc chỉ định đối tượng của lớp Comparer đó. Ví dụ như với
danh sách personList đã tạo ra, chúng ta sẽ sắp xếp danh sách này theo tuổi như sau:
empArray.Sort(new MyAgeComparer());

Còn nếu bạn muốn sắp xếp theo tên thì sao? Rất dễ dàng, chỉ cần thay đối tượng tương
ứng trong tham số của phương thức Sort:
empArray.Sort(new MyNameComparer());

VD: ta xem ví dụ đầy đủ bên dưới:
namespace Programming_CSharp
{
using System;
using System.Collections;
// một lớp đơn giản để lưu trữ trong mảng
public class Employee
{
public Employee(int age, string name)
{
this.age = age;
this.name = name;
}

public override string ToString()
{
return ( name.ToString()+":"+age.ToString());

}
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
// So s|nh được delegate cho Employee
// Employee sử dụng phương thức so sánh
// mặc địnhcủa số nguyên


private int age;
private string name;
}
class MyAgeComparer : IComparer
{

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×