C# là một ngụn ngữ định kiểu mạnh mẽ. Kiểu dữ liệu là tập hợp
cỏc giỏ trị mà một biến thuộc kiểu đú cú thể nhận được. Mỗi biến phải
khai bỏo thuộc một kiểu dữ liệu.
Cỏc kiểu dữ liệu trong ngụn ngữ C# chia làm hai loại, kiểu dữ
liệu xõy dựng sẵn và kiểu dữ liệu do người dựng định nghĩa. C# cũng
phõn loại cỏc kiểu dữ liệu thành hai loại: kiểu dữ liệu giỏ trị (value data
type), và kiểu dữ liệu tham chiếu (reference data type). Việc phõn chia
này 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ớ. Biến kiểu dữ liệu giỏ trị lưu giữ giỏ trị của nú trong
bộ nhớ tĩnh (stack). Trong khi đú biến kiểu tham chiếu, khụng chứa đối tượng thuộc kiểu này, mà lưu một địa chỉ hay tham chiếu đến đối tượng trong bộ nhớ stack, cũn đối tượng thật sự lưu trong bộ nhớ động
(heap). Nếu chỳng ta cú một đối tượng cú kớch thước rất lớn thỡ việc lưu giữ chỳng trờn bộ nhớ heap rất cú ớch. Tất cả cỏc kiểu dữ liệu cơ sở
xõy dựng sẵn là kiểu dữ liệu giỏ trị. Kiểu chuỗi và cỏc lớp định nghĩa
sẵn là kiểu dữ liệu tham chiếu. Và tất cả cỏc kiểu do người dựng định
nghĩa ngoại trừ kiểu cấu trỳc, liệt kờ đều là kiểu dữ liệu tham chiếu.
Ngoài ra C# cũng hỗ trợ kiểu con trỏ như C++, nhưng ớt khi được sử
dụng, khi làm việc với những đoạn mó lệnh cú sử dụng kiểu con trỏ, sẽ được đỏnh dấu khụng an toàn (unsafe).
2.2.1.1. Kiểu dữ liệu giỏ trị
Bao gồm cỏc kiểu dữ liệu cơ sở định nghĩa sẵn, kiểu liệt kờ và kiểu cấu trỳc. Kiểu dữ liệu cấu trỳc người dựng định nghĩa sẽ được
tỡm hiểu trong chương kế tiếp cựng với kiểu lớp và kiểu tham chiếu phương thức (delegate).
Kiểu cơ sở
Ngụn ngữ C# đưa ra cỏc kiểu dữ liệu cơ sở rất hữu dụng, mỗi
ỏnh xạ cỏc kiểu dữ liệu cơ sở 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 kỳ ngụn ngữ khỏc được
biờn dịch bởi .NET.
Cỏc kiểu dữ liệu cơ sở là kiểu dữ liệu struct xõy dựng sẵn chứa
nhiều thuộc tớnh và phương thức cần thiết, trong đú phương thức thường dựng là: Parse(string s): chuyển chuỗi s thành kiểu struct tương ứng
Vớ dụ: float a = float.Parse(s);
Bảng 2.1. Kiểu dữ liệu cơ sở
Kiểu Mụ tả Độ lớn Kiểu .Net Phạm vi
bool Kiểu logic 1 bit Boolean true, false char Ký tự
Unicode
16 bits Char
0 … 65535 byte Số nguyờn 8 bits Byte 0 … 255 sbyte Số nguyờn 8 bits SByte -128 … 127
short Số nguyờn 16 bits Int16 -32768 … 32767 ushort Số nguyờn 16 bits UInt16 0 ... 65535
int Số nguyờn 32 bits Int32 -2147483648 ... 2147483647 uint Số nguyờn 32 bits UInt32 0 ... 4294967295
long Số nguyờn 64 bits Int64 -9223372036854775808 … 9223372036854775807 ulong Số nguyờn 64 bits UInt64 0 ... 18446744073709551615
float Số thực 32 bits Single -3.402823E38 ... 3.402823E38 double Số thực 64 bits Double -1.79769313486232E308 …
1.79769313486232E308
decimal Số thực 64 bits Decimal -79228162514264337593543950335 …
Kiểu liệt kờ
Kiểu liệt kờ đơn giản là tập hợp cỏc tờn hằng cú giỏ trị khụng thay đổi, giỳp bạn tổ chức dữ liệu khoa học hơn, mó trong sỏng dễ
hiểu hơn. C# cung cấp rất nhiều kiểu liệt kờ định nghĩa sẵn, sẽ được đề cập đến trong cỏc chương kế tiếp.
Để định nghĩa một kiểu liệt kờ ta thực hiện theo cỳ phỏp sau:
enum TờnKiểuLiệtKờ [KiểuCơSở]
{
//Danh sỏch cỏc thành phần liệt kờ };
Một kiểu liệt kờ bắt đầu với từ khúa enum, tiếp sau là một định
danh cho kiểu liệt kờ.
Danh sỏch liệt kờ là cỏc hằng được gỏn giỏ trị và mỗi thành phần phải phõn cỏch nhau dấu phẩy. Nếu chỳng ta khụng khởi tạo giỏ
trị cho cỏc thành phần này thỡ chỳng sẽ nhận cỏc giỏ trị liờn tiếp bắt đầu từ 0. Mỗi tờn hằng trong kiểu liệt kờ thuộc bất kỳ một kiểu dữ
liệu cơ sở nguyờn nào như int, short, long..., ngoại trừ kiểu ký tự.
Kiểu cơ sở chớnh là kiểu khai bỏo cho cỏc thành phần liệt kờ. Nếu bỏ qua thành phần này thỡ trỡnh biờn dịch sẽ gỏn mặc định là kiểu nguyờn int. Khi đú, mỗi thành phần trong kiểu liệt kờ tương ứng với
một giỏ trị số nguyờn.
Khi truy xuất giỏ trị của danh sỏch liệt kờ, cần phải chuyển kiểu
một cỏch tường minh.
Vớ dụ: using System; class Example {
enum VisibleType {None = 0, Hidden = 2, Visible = 4}; // In ra tờn và giỏ trị thành phần của enum
static void Main(string[] args) {
VisibleType visEnum = VisibleType.Hidden; Console.WriteLine(visEnum.ToString()); Console.WriteLine((int) VisibleType.Hidden); }
}
Kiểu Nullable (Nullable type)
C# 2.0 cung cấp kiểu struct System.Nullable<T> thuộc khụng
gian tờn System cho phộp kiểu giỏ trị cú giỏ trị null. Tất cả kiểu dữ
liệu cú giỏ trị null tương ứng. Một kiểu Nullable cú thể biểu diễn một
dóy giỏ trị của kiểu tương ứng và giỏ trị null. Chẳng hạn như biến
kiểu Nullable<Int32> cú thể gỏn giỏ trị từ -2147483648 đến
2147483647 hay giỏ trị null.
Kiểu Nullable khai bỏo cho cỏc biến kiểu giỏ trị mà cú thể gỏn
giỏ trị null. Bạn khụng thể tạo một kiểu Nullable dựa trờn kiểu tham
chiếu. Kiểu tham chiếu đó hỗ trợ giỏ trị null là tham chiếu rỗng.
Cỳ phỏp T? sử dụng để khai bỏo kiểu Nullable<T>, trong đú T
là kiểu giỏ trị. Phộp toỏn ?? để gỏn giỏ trị mặc định của biến kiểu
Nullable cú giỏ trị là null, cho biến khụng cú kiểu Nullable.
Vớ dụ:
int? x = null; //x khụng chứa bất kỳ giỏ trị
int y = x ?? -1; //x chứa giỏ trị 0
int? a = default(int); //a chứa giỏ trị 0
int? b = default(int?); //b khụng chứa bất kỳ giỏ trị
Kiểu Nullable cung cấp thuộc tớnh và phương thức sau:
Value: Trả về giỏ trị của biến và phỏt sinh ngoại lệ
InvalidOperationException nếu biến kiểu Nullable khụng
chứa bất kỳ giỏ trị
Vớ dụ:
int c = a.Value; //trả về 0
HasValue: Trả về true nếu biến kiểu Nullable cú giỏ trị, ngược lại trả về false
Vớ dụ:
bool e = a.HasValue; //trả về true
bool f = b.HasValue; //trả về false
if (y.HasValue) Console.Write(x.Value);
GetValueOrDefault(): nếu biến kiểu Nullable cú giỏ trị, trả về
giỏ trị, ngược lại trả về giỏ trị mặc định của kiểu tương ứng
Vớ dụ:
int g = a.GetValueOrDefault(); //trả về 0
int h = b.GetValueOrDefault(); //trả về 0
2.2.1.2. Kiểu dữ liệu tham chiếu Kiểu chuỗi
Kiểu dữ liệu chuỗi (string hay String) là kiểu tham chiếu xõy
dựng sẵn, lưu giữ một dóy ký tự. Chuỗi trong C# là khụng thay đổi,
mỗi khi chuỗi thay đổi, một chuỗi mới được tạo ra để chứa chuỗi
kết quả.
Tạo một đối tượng chuỗi: Nhiều string được tạo từ cỏc hằng chuỗi. Khi trỡnh dịch bắt gặp một chuỗi ký tự bao giữa cặp nhỏy kộp,
nú tạo ra một đối tượng chuỗi cú giỏ trị là chuỗi này. Bạn cú thể dựng hằng chuỗi ở bất kỳ đõu bạn dựng đối tượng string
String s = "Hello World";
Hoặc string s = "Hello World";
Bạn cú thể tạo đối tượng chuỗi như bất kỳ đối tượng khỏc, dựng từ khoỏ new.
Khởi tạo chuỗi chứa 2 ký tự ‘a’
string s = new string('a', 2); //s = “aa” Khởi tạo chuỗi từ mảng ký tự
char[] ch = { 'a', 'b', 'c' };
string s = new string(ch); //s = “abc”
Khởi tạo chuỗi từ 2 phần tử trong mảng ch, bắt đầu từ phần tử
thứ 1:
string s = new string(ch, 1, 2); //s = “bc”
Chuyển kiểu thành kiểu String: Để chuyển 1 kiểu dữ liệu nào
đú về String, sử dụng phương thức đối tượng ToString() của đối tượng cần chuyển kiểu, hay phương thức tĩnh ToString của lớp
Convert.
Vớ dụ:
int Number = 10;
String Str = Number.ToString(); Str = Convert.ToString(Number);
Truy cập từng ký tự của chuỗi:
Truy cập cỏc ký tự của chuỗi bằng chỉ số và sử dụng dấu [] như
mảng, chỉ số cú giỏ trị bắt đầu từ 0, vớ dụ s[0].
Cỏc thuộc tớnh và phương thức thường dựng của string:
int Length : Cho chiều dài chuỗi int len = Str.Length;
int len = "Hello World".Length;
bool Equals(string value)
bool Equals(string value, StringComparision comparisionType): kiểm tra hai chuỗi cú giỏ trị bằng nhau khụng, trả về true nếu 2
chuỗi cú giỏ trị bằng nhau, ngược lại trả về false, hoặc cú thể sử
dụng dấu = để so sỏnh chuỗi
Vớ dụ:
string s1 = "Hello"; string s2 = s1;
//So sỏnh chuỗi khụng phõn biệt hoa thường Console.WriteLine(s1.Equals(s2, StringComparison.OrdinalIgnoreCase)); Console.WriteLine("s1 == s2 : "+(s1==s2)); Kết quả là : s1 equals s2 : True True s1 == s2 : True
int CompareTo(string value): So sỏnh 2 chuỗi, trả về giỏ trị
nếu < 0 : chuỗi nhỏ hơn value
nếu > 0 : chuỗi lớn hơn value
nếu = 0 : chuỗi bằng value
int IndexOf(char value), int IndexOf(string value): Trả về vị
trớ tỡm thấy đầu tiờn của ký tự hay chuỗi value
int IndexOf(char value, int startIndex), int IndexOf(string value, int startIndex): Trả về vị trớ tỡm thấy đầu tiờn của ký
tự hay chuỗi value kể từ vị trớ startIndex đến cuối chuỗi int IndexOf(string value, StringComparision comparisionType):
Trả về vị trớ tỡm thấy đầu tiờn của chuỗi value với kiểu so sỏnh
phõn biệt hoa thường hay khụng
int IndexOf(char value, int startIndex, int count), int IndexOf(string value, int startIndex, int count): Trả về vị trớ
tỡm thấy đầu tiờn của ký tự hay chuỗi value trong count ký
tự của chuỗi kể từ vị trớ startIndex
int IndexOf(string value, int startIndex, StringComparision comparisionType)
int IndexOf(string value, int startIndex, int count, StringComparision comparisionType)
Tương tự phương thức IndexOf, cú 9 phương thức LastIndexOf
string Substring(int startIndex): Trả về chuỗi con của một chuỗi bắt đầu từ vị trớ startIndex đến cuối chuỗi
string Substring(int startIndex, int length): Trả về chuỗi con gồm length ký tự của một chuỗi bắt đầu từ vị trớ startIndex
string org = "This is a test";
string result1 = org.Substring(10); //result1 = “test” string result2 = org.Substring(8,1); //result2 = “a”
string Replace(string oldValue, string newValue): Trả về
chuỗi sau khi thay thế tất cả cỏc lần xuất hiện của chuỗi
oldValue bằng chuỗi newValue
string Trim(): Trả về chuỗi sau khi cắt bỏ khoảng trống đầu
và cuối chuỗi
string TrimEnd(): Trả về chuỗi sau khi cắt bỏ khoảng trống
cuối chuỗi
string TrimStart(): Trả về chuỗi sau khi cắt bỏ khoảng trống đầu chuỗi
string ToLower(): Trả về chuỗi thường của chuỗi string ToUpper(): Trả về chuỗi chữ hoa của chuỗi
string s = "This is a test"; string upper = s.ToUpper();
bool EndsWith(string s): Kiểm tra chuỗi kết thỳc bởi 1
chuỗi xỏc định s hay khụng
bool StartsWith(string s): Kiểm tra chuỗi bắt đầu bởi 1
chuỗi xỏc định s hay khụng
string Insert(int index, string value): Trả về chuỗi sau khi
chốn chuỗi value vào chuỗi tại vị trớ index
string Remove(int index): Xúa chuỗi kể từ vị trớ index đến
cuối chuỗi, và trả về chuỗi mới sau khi xúa
bool StartsWith(string value): bool StartsWith(string value, StringComparison comparisonType), bool StartsWith(string
value, bool ignoreCase, CultureInfo culture): Trả về true
nếu chuỗi bắt đầu bởi chuỗi value, ngược lại trả về false.
ComparisonType chỉ kiểu so sỏnh chuỗi, là cỏc hằng liệt kờ của enum StringComparison như OrdinalIgnoreCase: khụng
phõn biệt hoa thường, Ordinal, CurrentCulture: so sỏnh theo
ngụn ngữ hiện hành.
string[] Split(params char[] seperator): Trả về một mảng
cỏc chuỗi con được phõn tỏch bởi một trong cỏc ký tự trong
mảng seperator
string[] Split(char[] seperator, StringSplitOptions options): Trả về một mảng cỏc chuỗi con được phõn tỏch bởi một
trong cỏc ký tự trong mảng separator. Tham đối StringSplitOptions.RemoveEmptyEntries để xúa cỏc chuỗi
con rỗng, ngược lại khụng xúa chuỗi con rỗng sử dụng tựy chọn StringSplitOptions.None.
Vớ dụ: using System; class Program {
static void Main() {
string s = "there, is a cat"; string[] words = s.Split(' ', ','); foreach (string word in words) Console.WriteLine(word);
char[] delimiters = new char[] { ' ', ','};
words = s.Split(delimiters, StringSplitOptions.RemoveEmptyEntries); foreach (string word in words)
Console.WriteLine(word); }
}
Toỏn tử +: Để nối hai đối tượng string, hay một đối tượng string và một giỏ trị khỏc thành đối tượng string
Vớ dụ: Console.WriteLine("Nghiệm là " + x1 + " và " + x2);
static string Concat(params object[]): Nối nhiều đối tượng
thành một chuỗi
Console.WriteLine(string.Concat("Nghiệm là ", x1, " và ", x2);
static string Format(string format, params object[]): Trả về
chuỗi bằng cỏch thay thế cỏc ký hiệu đỏnh dấu trong chuỗi
format bởi cỏc tham đối theo sau chuỗi. Cú thể định dạng cỏc đối tượng object tương tự định dạng kết xuất của phương thức Write trỡnh bày cuối chương.
string.Format("Nghiệm là {0} và {1}", x1, x2); string.Format("{0:dd/MM/yyyy}", DateTime.Today); string.Format("{0:n2}", 12345678); string.Format("{0:c0}", 12345678); string.Format("{0:0.##}", 123.4567); Kiểu mảng
Mảng là một cấu trỳc lưu giữ cỏc thành phần cựng kiểu. Mỗi thành phần của mảng được truy xuất bởi chỉ số của nú trong mảng.
Mảng 1 chiều:
Khai bỏo một biến dựng để tham chiếu đến mảng, nhưng
khụng cú mảng nào thật sự tồn tại
KiểuPhầnTử[] TờnMảng;
Kiểu phần tử là kiểu dữ liệu của cỏc thành phần của mảng, cú thể là bất kỳ kiểu giỏ trị hay tham chiếu.
Vớ dụ: int[] m;
Tạo một mảng: Sử dụng toỏn tử new để cấp phỏt bộ nhớ cho
mảng và gỏn mảng đến biến đó khai bỏo
TờnMảng = new KiểuPhầnTử[KớchThướcMảng]; Kớch thước mảng là số thành phần trong mảng
Vớ dụ: m = new int[10];
Cú thể kết hợp khai bỏo biến mảng và tạo mảng như sau:
KiểuPhầnTử[] TờnMảng = new KiểuPhầnTử[KớchThướcMảng];
Vớ dụ:
int[] m = new int[10];
string[] myStrings = new string[3];
Truy xuất thành phần của mảng: TờnMảng[ChỉMục]
Chỉ mục: chỉ vị trớ của thành phần trong mảng cần truy xuất, cú thể là giỏ trị, biến hay biểu thức và cú giỏ trị từ 0 đến Kớch thước
mảng - 1
Vớ dụ: m[0] = 20;
Lấy kớch thước mảng: TờnMảng.Length
Khai bỏo, cấp phỏt bộ nhớ và khởi tạo giỏ trị đầu của mảng: Mảng cú thể khởi tạo khi khai bỏo sử dụng toỏn tử new hay
khụng. Mảng khởi tạo là danh sỏch cỏc biểu thức cỏch nhau
dấu phẩy, đặt trong ngoặc múc. Chiều dài mảng là số thành phần giữa hai dấu { và }
Vớ dụ: int[] numbers = new int[5] {1, 2, 3, 4, 5}; Cú thể bỏ qua kớch thước của mảng như sau:
int[] numbers = new int[] {1, 2, 3, 4, 5};
string[] names = new string[] {"Xuan", "Ha", "Thu"}; Cũng cú thể bỏ qua toỏn tử new như sau:
int[] numbers = {1, 2, 3, 4, 5};
string[] names = {"Xuan", "Ha", "Thu"};
int[] monthDays = {31,28,31,30,31,30,31,31,30,31,30,31};
C# cũng hỗ trợ mảng khụng kiểu bằng cỏch tạo mảng cỏc đối tượng như sau:
object[] arr = {1,"Hi there", 5.5};
Biến kiểu khụng tường minh (Implicitly typed local
khởi tạo giỏ trị đầu cho mảng mà khụng cần khai bỏo kiểu tường minh (implicitly typed local variable) như sau:
var arr = new int[] {1, 2, 3, 4, 5};
Vớ dụ: using System; namespace ThamDoi { class ThamDoi {
static void Main(string[] args) {
for (int i=0; i < args.Length; i++)
Console.WriteLine("Tham doi thu "+i+": "+args[i]); }
} }
Biờn dịch và chạy chương trỡnh: csc Thamdoi.cs
ThamDoi Thu tham doi dong lenh
Cho kết quả: Tham doi thu 0 : Thu Tham doi thu 1 : tham …
Mảng đa chiều (Array of arrays):
Mảng cú thể chứa cỏc thành phần là mảng:
Để khai bỏo một biến mảng đa chiều cần xỏc định mỗi chiều của mảng bằng cỏch sử dụng cỏc cặp dấu ngoặc
vuụng.
Vớ dụ: Khai bỏo mảng 2 chiều m là một mảng 4 dũng, và cú thành phần là cỏc số nguyờn.
int[][] m = new int[4][];
m[0] = new int[2]; //dũng 1 cú 2 cột
m[1] = new int[5]; //dũng 2 cú 5 cột
Hay cú thể khai bỏo như sau:
double[,] myDoubles = new double[2, 2]; int[,,] myInts = new int[4,5,3];
Truy xuất thành phần của mảng m[i][j] (phần tử tại dũng i, cột j). Với i là chỉ số dũng, cú giỏ trị từ 0 đến số dũng -1, j là chỉ số cột, cú giỏ trị từ 0 đến số cột – 1. Hay m[i,j].
Lấy kớch thước mảng:
Với mảng khai bỏo như sau: int[][] m = new int[4][];
Kớch thước của chiều thứ nhất, nghĩa là số dũng: m.Length.
Kớch thước của chiều thứ hai, nghĩa là số cột.
Số phần tử trờn dũng cú thể khỏc nhau trờn mỗi dũng. Ta cú
kớch thước của dũng thứ i m[i].Length
Với mảng khai bỏo như sau: int[,] m = new int[4,5]; Số tất cả cỏc phần tử mảng ở tất cả cỏc chiều: m.Length
Kớch thước của chiều thứ nhất, nghĩa là số dũng: m.GetLength(0);
Kớch thước của chiều thứ hai, nghĩa là số cột: m.GetLength(1);
Khai bỏo, cấp phỏt bộ nhớ và khởi tạo giỏ trị đầu của mảng
Vớ dụ:
int[,] numbers = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} };