Lập trình C#

Các kiểu dữ liệu trong lập trình C#

Các kiểu dữ liệu trong lập trình C#
Được viết bởi Minh Hoàng

Series lập trình C#, ngôn ngữ lập trình hiện đại và mạnh mẽ.

Kiểu dữ liệu là gì ?

Kiểu dữ liệu (data type) là một sự quy định về cấu trúc, miền trị của dữ liệu và tập các phép toán tác động lên miền trị đó.

Một ngôn ngữ lập trình chỉ chấp nhận và xử lý những dữ liệu tuân theo sự quy định về kiểu của ngôn ngữ lập trình đó. Trong một ngôn ngữ lập trình, một dữ liệu bao giờ cũng thuộc về một kiểu dữ liệu nhất định.

Trong C# dữ liệu được phân loại thành mấy kiểu ?

Dữ liệu được phân loại thành 3 kiểu:

  1. Kiểu tham trị (Value type)
  2. Kiểu tham chiếu (Reference type)
  3. Kiểu con trỏ (Pointer type)

Nội dung chi tiết:

1. Kiểu tham trị (Value type)
Các biến kiểu tham trị lưu giữ trực tiếp dữ liệu của chúng và được cấp phát bộ nhớ trên Stack để lưu giá trị đó. Chúng được kế thừa từ lớp System.ValueType.

Ví dụ: khi khai báo int, char, float,… thì tương ứng các biến có kiểu dữ liệu này sẽ lưu trữ giá trị số nguyên, ký tự, và số thực…

Bảng sau sẽ mô tả một số kiểu tham trị (Kiểu dữ liệu được xây dựng sẵn):
Kiểu C# Số byte Kiểu .NET Mô tả
byte 1 Byte Số nguyên dương không dấu từ 0-255
char 2 Char Ký tự Unicode
bool 1 Boolean Giá trị logic true/ false
sbyte 1 Sbyte Số nguyên có dấu (từ -128 đến 127)
short 2 Int16 Số nguyên có dấu giá trị từ -32768 đến 32767
ushort 2 UInt16 Số nguyên không dấu 0 – 65.535
int 4 Int32 Số nguyên có dấu, giá trị từ –2.147.483.648 đến 2.147.483.647
uint 4 UInt32 Số nguyên không dấu 0 – 4.294.967.295
float 4 Single Kiểu dấu chấm động, giá trị xấp xỉ từ -3.402823e38 đến 3.402823e38
double 8 Double Kiểu dấu chấm động có độ chính xác gấp đôi, giá trị từ -1.79769313486232e308 đến 1.79769313486232e308.
decimal 8 Decimal Từ -79228162514264337593543950335 đến 79228162514264337593543950335 , được dùng trong tính toán tài chính, kiểu này đòi hỏi phải có hậu tố “m” hay “M” theo sau giá trị.
long 8 Int64 Kiểu số nguyên có dấu có giá trị trong khoảng: -9.223.370.036.854.775.808 đến 9.223.372.036.854.775.807
ulong 8 UInt64 Số nguyên không dấu từ 0 đến 18,446,744,073,709,551,615

■ Ngoài ra còn có 2 kiểu tham trị đặc biệt là kiểu struct, enum chúng ta sẽ cùng tìm hiểu trong một bài riêng.

Code minh họa:
[code language=”csharp”] using System;

namespace MinhHoangBlog
{
class KieuThamTriCSharp
{
static void Main(string[] args)
{
/*
* Khai báo biến và khởi tạo giá trị
*/
// Kiểu số nguyên
int valInt = 8;
byte valByte = 6;
short valShort = 2017;

// Kiểu số thực
float valFloat = 10.9f; // Giá trị của biến kiểu float phải có hậu tố f hoặc F.
double valDouble = 10.9; // Giá trị của biến kiểu double không cần hậu tố.
decimal valDecimal = 10.9m; // Giá trị của biến kiểu decimal phải có hậu tố m hoặc M.

// Kiểu ký tự và kiểu chuỗi
char valChar = ‘M’; // Giá trị của biến kiểu ký tự nằm trong cặp dấu ” (nháy đơn).
string valString = "MinhHoangBlog"; // Giá trị của biến kiểu chuỗi nằm trong cặp dấu "" (nháy kép).

/*
* Dùng từ khóa << typeof >> để biết Type của kiểu dữ liệu
*/
Type typeUint = typeof(uint);
Console.WriteLine(typeUint.Name); // Output: UInt32

Type typeFloat = typeof(float);
Console.WriteLine(typeFloat.Name); // Output: Single

/*
* Dùng từ khóa << sizeof >> để biết Size của kiểu dữ liệu
*/
Console.WriteLine("Kieu char co: {0} bytes", sizeof(char)); // Output: 2
Console.WriteLine("Kieu long co: {0} bytes", sizeof(long)); // Output: 8
Console.WriteLine("Kieu double co: {0} bytes", sizeof(double)); // Output: 8
Console.ReadLine();

/*
* Dùng hằng << MinValue, MaxValue >> để biết Range của kiểu dữ liệu
*/
// Dùng type C# để check
Console.WriteLine(int.MinValue); // Output: –2147483648
Console.WriteLine(int.MaxValue); // Output: 2147483647

//Hoặc cũng có thể dùng type .Net để check
Console.WriteLine(Int32.MinValue); // Output: –2147483648
Console.WriteLine(Int32.MaxValue); // Output: 2147483647

Console.ReadKey();
}
}
}
[/code]

2. Kiểu tham chiếu (Reference type)

– Kiểu dữ liệu này chứa địa chỉ của vùng nhớ, nơi lưu giá trị thật của biến chứ không trực tiếp lưu giá trị của biến, nó tham chiếu tới một vùng nhớ được cấp phát trên bộ nhớ Heap (khác với kiểu tham trị là nó lưu trực tiếp giá trị của biến)

– Bạn có thể hình dung qua hình minh họa:

Kiểu tham trị, tham chiếu trong lập trình C#

Kiểu tham trị, tham chiếu trong lập trình C#

– Một số kiểu tham chiếu là: object, string, class, delegate, interface, array, dynamic, kiểu do lập trình viên tự định nghĩa (thực ra nó cũng là kiểu class, ví dụ như class Student, class Animal,… )

– Trong đó, kiểu object là lớp cơ sở cơ bản cho tất cả kiểu dữ liệu trong C# Common Type System (CTS). Object là một alias cho lớp System.Object. Các kiểu object có thể được gán giá trị của bất kỳ kiểu, kiểu giá trị, kiểu tham chiếu, kiểu tự định nghĩa (user-defined) khác. Tuy nhiên, trước khi gán giá trị, nó cần một sự chuyển đổi kiểu.

Khi một kiểu giá trị được chuyển đổi thành kiểu object, nó được gọi là boxing và ngược lại, khi một kiểu object được chuyển đổi thành kiểu giá trị, nó được gọi là unboxing.

[code language=”csharp” highlight=”10,13,19-22″] using System;

namespace MinhHoangBlog
{
class ObjectTypeDemo
{
static void Main(string[] args)
{
int num = 123;
object obj = (object)num; // boxing

obj = 123;
num = (int)obj; // unboxing

// Khai báo mảng kiểu object
object[] arrObj = new object[4];

// Kiểu object có thể nhận giá trị của bất kỳ các kiểu dữ liệu khác
arrObj[0] = true;
arrObj[1] = 1987;
arrObj[2] = "Hello World!";
arrObj[3] = 5.2;

int ii = 0;
Console.WriteLine( "Cac gia tri cua mang: " );
do
{
Console.WriteLine(arrObj[ii]);
ii++;
}
while (ii < arrObj.Length);

Console.ReadKey();
}
}
}
[/code]

– Các kiểu tham chiếu còn lại như Class, Interface, Delegate, Dynamic,… chúng ta sẽ nói chi tiết từng loại trong các bài viết tiếp theo.

3. Kiểu con trỏ (Pointer type)

– Các biến kiểu con trỏ lưu giữ địa chỉ bộ nhớ của kiểu khác. Các con trỏ trong C# có khả năng như con trỏ trong C hoặc C++.

– C# cho phép sử dụng các biến con trỏ trong một hàm của khối code khi nó được đánh dấu bởi từ khóa unsafe. Khái niệm unsafe code hoặc unmanaged code trong C# là một khối code có sử dụng biến con trỏ.

■ Từ khóa unsafe có thể được sử dụng trong các trường hợp sau:

[code language=”csharp”] // Dùng với function(method)
unsafe string DoSomething()
{
// code có sử dụng con trỏ
}
[/code]

[code language=”csharp”] // Dùng với class
unsafe class MyClass()
{
// có method bất kỳ sử dụng con trỏ
}
[/code]

[code language=”csharp”] // Dùng với field của class
class MyClass()
{
unsafe int* p; // khai báo 1 field là biến con trỏ
}
[/code]

[code language=”csharp”] // Dùng với struct
unsafe struct Books
{
// có method bất kỳ sử dụng con trỏ
};
[/code]

[code language=”csharp”] // Dùng với Block code
void MyMethod()
{
// phần ‘safe’ code không sử dụng con trỏ

unsafe
{
// phần unsafe code sử dụng con trỏ
}

// phần ‘safe’ code không sử dụng con trỏ
}
[/code]

■ Từ khóa unsafe KHÔNG ĐƯỢC DÙNG cho biến cục bộ

[code language=”csharp”] void MyMethod()
{
unsafe int* p; // SAI, không được dùng.
}
[/code]

– Cú pháp để khai báo một kiểu con trỏ trong C# là:

[code language=”csharp”]Kiểu* TênBiến;[/code]

– Để biên dịch và chạy các chương trình trong chế độ unsafe, bạn right click vào Project, sau đó chọn Properties > Build > check chọn Allow unsafe code, xong nhấn tổ hợp phím Ctrl + S để lưu thay đổi, rồi build project:

Thiết lập Project chạy ở chế độ unsafe

Thiết lập Project chạy ở chế độ unsafe

Code minh họa:
[code language=”csharp”] using System;

namespace MinhHoangBlog
{
class KieuConTro
{
static unsafe void Main(string[] args)
{
int* pInt1, pInt2, pInt3; /* pInt1, pInt2, pInt3 là 3 biến con trỏ tham chiếu đến kiểu nguyên */
int** ppInt1; /* ppInt1 là một con trỏ tham chiếu đến con trỏ đến kiểu nguyên */
int*[] ppInt2; /* ppInt2 là một mảng của các con trỏ tham chiếu đến kiểu nguyên */
double* pDbl; /* pDbl là một con trỏ tham chiếu đến kiểu số thực */
char* pChar; /* pChar là một con trỏ tham chiếu đến kiểu ký tự */
void* pVoid; /* pVoid là con trỏ tham chiếu đến kiểu void, KHÔNG NÊN DÙNG tùy ý */

int num = 20;
int* p = &num; /* Khai báo 1 biến con trỏ p, trỏ vào địa chỉ của biến num */

Console.WriteLine("Gia tri cua bien num: {0} ", num);
Console.WriteLine("Gia tri cua bien num: {0}", p->ToString());
Console.WriteLine("Gia tri cua bien num: {0}", *p);

Console.WriteLine("Dia chi cua bien num: {0}", (int)p);

Console.ReadKey();
}
}
}
[/code]

Cảm ơn bạn đã theo dõi. Đừng ngần ngại hãy cùng thảo luận với chúng tôi!

Giới thiệu

Minh Hoàng

Xin chào, tôi là Hoàng Ngọc Minh, hiện đang làm BrSE, tại công ty Toyota, Nhật Bản. Những gì tôi viết trên blog này là những trải nghiệm thực tế tôi đã đúc rút ra được trong cuộc sống, quá trình học tập và làm việc. Các bài viết được biên tập một cách chi tiết, linh hoạt để giúp bạn đọc có thể tiếp cận một cách dễ dàng nhất. Hi vọng nó sẽ có ích hoặc mang lại một góc nhìn khác cho bạn[...]

5 bình luận

Translate »