Lập trình C#

Kiểu struct trong lập trình C#

Kiểu struct 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 struct trong lập trình C#

– Trước khi vào bài. Chúng ta cùng xét bài toán đơn giản: chẳng hạn như một lớp có 100 sinh viên mỗi sinh viên gồm họ tên và mã sinh viên. Hãy nhập dữ liệu cho lớp đó? Có thể bạn sẽ nghĩ đến cách dùng 2 mảng: 1 mảng lưu họ tên, 1 mảng lưu mã sinh viên!? Nếu dùng cách này thì hoàn toàn đúng không sai,…

– Nhưng hãy xem yêu cầu tiếp theo: Thi học kỳ xong, hãy nhập điểm cho từng sinh viên, mỗi sinh viên gồm 10 môn (Toán, Tin, Hóa, Vật lý,…). Bạn thấy sao nào… Chúng ta cần dùng 12 mảng để lưu được tất cả các thông tin này chăng!?… Nếu vậy thì vất vả quá nhỉ! không nên… Lúc này bạn hãy nghĩ đến kiểu cấu trúc struct.

– Trong bài này, chúng ta sẽ cùng tìm hiểu về kiểu cấu trúc struct với các nội dung:

  1. Kiểu cấu trúc struct là gì? Đặc điểm của struct
  2. Cách khai báo và sử dụng struct
1. Kiểu cấu trúc struct là gì? Đặc điểm của struct
1. Kiểu cấu trúc struct là gì? Đặc điểm của struct
#1. Kiểu cấu trúc struct là gì?

struct là một kiểu dữ liệu có cấu trúc, được kết hợp từ các kiểu dữ liệu nguyên thủy do người lập trình định nghĩa để thuận tiện trong việc quản lý dữ liệu và lập trình.

– Đối với mảng, chỉ có thể lưu các thông tin có cùng kiểu dữ liệu. Nhưng với kiểu cấu trúc struct chúng ta có thể lưu thông tin thuộc nhiều kiểu dữ liệu khác nhau và chúng có liên quan với nhau.

#2. Đặc điểm của kiểu cấu trúc struct
  • struct là kiểu tham trị.
  • struct có thể có các thành phần là methods, fields, indexers, properties, operator methods, và events.
  • struct có định nghĩa constructor, nhưng không có destructor. Tuy nhiên, default constructor(constructor không tham số) được định nghĩa ngầm định một cách tự động và chúng ta không thể thay đổi. Còn constructor có tham số thì số lượng tham số cần phải đầy đủ tương ứng với các fields, không đủ sẽ bị lỗi.
  • struct không được kế thừa từ một struct hay một class. Và nó cũng không thể là một base class hay base struct.
  • Do đó các thành phần của struct không thể đi kèm với các từ khóa liên quan đến kế thừa là: abstract, virtual, hay protected.
  • struct có thể implement từ một hoặc nhiều interface.
  • Khi tạo một đối tượng struct bằng từ khóa new, một constructor thích hợp sẽ được gọi để tạo đối tượng. Không giống class, biến kiểu struct có thể được tạo ra mà không cần dùng từ khóa new.
  • Nếu không dùng từ khóa new thì các fields chưa được gán giá trị, nếu dùng object struct truy xuất vào để lấy giá trị xử lý thì sẽ bị lỗi: CS0170 Use of possibly unassigned field ‘tên_field’ (field chưa dc khởi tạo giá trị thì nó cũng không nhận giá trị mặc định của kiểu dữ liệu được khai báo).
#3. Nên dùng kiểu struct khi nào?

– Sử dụng kiểu struct khi bạn chỉ muốn lưu thông tin và hiển thị thông tin thôi. Không có nhu cầu kế thừa hay các thao tác phức tạp nâng cao như kiểu class.

– Một ví dụ trong thực tế mình đã áp dụng là:

  • Như các bạn biết kiểu tập hợp enum thì mỗi phần tử sẽ đại diện cho một số nguyên interger. Chúng ta không thể thay đổi bằng kiểu dữ liệu khác được.
  • Vậy trong trường hợp, chúng ta muốn sử dụng một kiểu tập hợp dạng như enum với mỗi phần tử đại diện cho kiểu dữ liệu khác integer thì phải làm thế nào!? Khi đó bạn có thể dùng struct để thay thế như sau:
[code language=”csharp” highlight=”2″] // Create a struct that saves the converted value of the meter
public struct ConversionValue
{
public const double METERS = 1.0;
public const double CENTIMETERS = 100.0;
public const double MILLIMETERS = 1000.0;
public const double FEET = 3.2804;
public const double INCHES = 39.37007;
public const double YARDS = 1.09361;
public const double KILOMETERS = 0.001;
public const double MILES = 0.000621371;
public const double MICROMETERS = 1000000.0;
public const double MILS = 39370.07874;
public const double MICROINCHES = 39370079.0;
}
[/code]

– Ở ví dụ này mình muốn tạo ra một tập hợp quy định cách quy đổi khoảng cách từ mét(m) sang các đơn vị khác, mỗi phần tử của struct ConversionValue sẽ đại diện cho một giá trị kiểu double, và khi sử dụng cần giá trị quy đổi tương ứng nào sẽ lấy ra bằng cách: ConversionValue.METERS, hay ConversionValue.INCHES,… Tương tự vậy, bạn có thể tạo ra một struct bất kỳ với mỗi phần tử đại diện cho một kiểu dữ liệu mong muốn phụ thuộc vào từng xử lý logic cụ thể.

2. Cách khai báo và sử dụng struct
2. Cách khai báo và sử dụng struct
#1. Cách khai báo

– Một struct thì có thuộc tính (là các danh từ) và phương thức (là các động từ). Được khai báo bắt đầu bằng từ khóa struct như sau:

<access modifier> struct tên_struct
{
   // Khai báo các thuộc tính
   <access modifier> <kiểu_dữ_liệu> tên_biến_1;
   <access modifier> <kiểu_dữ_liệu> tên_biến_2;
   ...
   <access modifier> <kiểu_dữ_liệu> tên_biến_n;
   
   // Khai báo các phương thức
   <access modifier> <kiểu_trả_về> tên_phương_thức_1(danh_sách_tham_số)
   {
      // định nghĩa phương thức
   }
   <access modifier> <kiểu_trả_về> tên_phương_thức_2(danh_sách_tham_số)
   {
      // định nghĩa phương thức
   }
   ...
   <access modifier> <kiểu_trả_về> tên_phương_thức_n(danh_sách_tham_số)
   {
      // định nghĩa phương thức
   }
}

Trong đó:

  • access modifier chỉ định phạm vi truy cập:
    • Đối với của tên_struct chỉ được là public hoặc internal. Không được là private, protectedprotected internal.
    • Đối với thành viên thì có thể là public, internalprivate. Không được là protected hay protected internal.
  • struct : từ khóa dùng để khai báo một kiểu cấu trúc.
  • tên_struct, tên_biến, tên_phương_thức : tuân thủ theo quy tắc đặt tên trong lập trình.
  • kiểu_trả_về : có thể là kiểu dữ liệu có sẵn của .Net, hoặc là kiểu dữ liệu do người dùng tự định nghĩa.
#2. Cách sử dụng

– Cũng giống như class chúng ta cũng có thể truy xuất đến từng thành phần dữ liệu của struct thông qua toán tử dấu chấm “.” kèm theo tên thành phần muốn truy xuất.

Ví dụ 1: Demo sử dụng toán tử new tạo đối tượng struct để lưu trữ thông tin của một cuốn sách trong thư viện:

struct:
    string Title
    string Author
    int BookId
    DateTime PublishDay
[code language=”csharp” highlight=”6,15,47,53″] using System;

namespace MinhHoangBlog
{
// Khai báo struct thông tin sách
struct Books
{
// Biến thành viên
private string Title;
private string Author;
private int BookId;
private DateTime PublishDay;

// Constructor có tham số
public Books( string Title, string Author, int BookId, DateTime PublishDay )
{
this.Title = Title;
this.Author = Author;
this.BookId = BookId;
this.PublishDay = PublishDay;
}

// Set thông tin sách
public void SetInfo( string inTitle, string inAuthor, int inBookId, DateTime inPublishDay )
{
Title = inTitle;
Author = inAuthor;
BookId = inBookId;
PublishDay = inPublishDay;
}

// Hiển thị thông tin sách
public void DisplayInfo()
{
Console.WriteLine("Title : {0}", Title);
Console.WriteLine("Author : {0}", Author);
Console.WriteLine("Book ID : {0}", BookId);
Console.WriteLine("Publish date : {0}", PublishDay.ToString( "yyyy/MM/dd" ));
}
}; // Dấu chấm phẩy「,」có thể có hoặc không.

class Program
{
static void Main(string[] args)
{
// Tạo đối tượng struct Book1 bằng constructor mặc định
Books Book1 = new Books();

// Set thông tin sách cho Book1
Book1.SetInfo("C Programming", "Nuha Ali", 6495407, DateTime.Now);

// Tạo đối tượng struct Book2 bằng constructor có tham số
Books Book2 = new Books("C# Tutorial", "Zara Ali", 6495700, new DateTime(2011, 2, 19));

// In thông tin Book1
Book1.DisplayInfo();

Console.WriteLine();

// In thông tin Book2
Book2.DisplayInfo();

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

Kết quả chương trình

Kết quả chương trình


Ví dụ 2: Chúng ta sẽ không dùng toán tử new để tạo đối tượng struct. Trong trường hợp này, các fields của struct phải có access modifier là public.

[code language=”csharp” highlight=”6,21,22″] using System;

namespace MinhHoangBlog
{
// Khai báo struct thông tin sách
struct Books
{
// Biến thành viên phải là public
public string Title;
public string Author;
public int BookId;
public DateTime PublishDay;

}; // Dấu chấm phẩy「,」có thể có hoặc không.

class Program
{
static void Main(string[] args)
{
// Khai báo 2 biến struct không dùng từ khóa new
Books Book1;
Books Book2;

// Vì không sử dụng từ khóa new để tạo đối tượng struct Book1
// Nên ở đây [Book1.subject] chưa được khởi tạo mà truy xuất
// Sẽ bị lỗi
//string str = Book1.subject;

// Khởi tạo thông tin cho Book1
Book1.Title = "C Programming";
Book1.Author = "Nuha Ali";
Book1.BookId = 6495407;
Book1.PublishDay = DateTime.Now;

// Khởi tạo thông tin cho Book2
Book2.Title = "C# Tutorial";
Book2.Author = "Zara Ali";
Book2.BookId = 6495700;
Book2.PublishDay = new DateTime(2011, 2, 19);

// In thông tin Book1
Console.WriteLine("Title : {0}", Book1.Title);
Console.WriteLine("Author : {0}", Book1.Author);
Console.WriteLine("Book ID : {0}", Book1.BookId);
Console.WriteLine("Publish date : {0}", Book1.PublishDay.ToString( "yyyy/MM/dd" ));

Console.WriteLine();

// In thông tin Book2
Console.WriteLine("Title : {0}", Book2.Title);
Console.WriteLine("Author : {0}", Book2.Author);
Console.WriteLine("Book ID : {0}", Book2.BookId);
Console.WriteLine("Publish date : {0}", Book2.PublishDay.ToString( "yyyy/MM/dd" ));

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

Kết quả chương trình

Kết quả chương trình

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[...]

2 bình luận

Translate »