Class trong C#

Khi tạo một class có nghĩa là bạn đang tạo một bản kế hoạch chi tiết cho một kiểu dữ liệu.

Điều này thực sự không định nghĩa bất kỳ dữ liệu nào, nhưng nó xác định tên lớp có nghĩa là gì, các đặc tính (thuộc tính) và hành vi (phương thức) của lớp.

Đối tượng là các thể hiện của một lớp. Các phương thức và thuộc tính của lớp được gọi là thành viên của lớp.

Vậy class trong C# là gì? Làm sao để định nghĩa và sử dụng class trong C#? Bài viết này sẽ hướng dẫn chi tiết cho bạn.

Class trong C# là gì?

Class trong lập trình hướng đối tượng là tập hợp các đối tượng có cùng chung đặc điểm, hành vi, phương thức hoạt đột.

Class trong C# chính là cách thể hiện khái niệm về class trong lập trình hướng đối tượng.

Định nghĩa một class

Định nghĩa lớp bắt đầu với từ khóa class theo sau là tên class; phần thân của class được bao quanh bởi một cặp dấu ngoặc nhọn {}.

Sau đây là hình thức chung của một class:

<access specifier> class  ClassName 
{
   // member properties
   <access specifier> <data type> Property1 { get; set; }
   <access specifier> <data type> Property2 { get; set; }
   
   // constructors
   <access specifier> ClassName()
   {
  	   // constructor body
   }
   <access specifier> ClassName(parameter_list)
   {
  	   // constructor body
   }
   
   
   
   // member methods
   <access specifier> <return type> Method1(parameter_list) 
   {
      // method body
   }
   <access specifier> <return type> Method2(parameter_list) 
   {
      // method body
   }
}

Giải thích ý nghĩa:

  • access specifier: là chỉ thị truy cập xác định các quy tắc truy cập cho các thành viên cũng như chính lớp đó. Có các từ khóa chỉ thị truy cập sau: public, internal, protected, private. Nếu không được chỉ định thì chỉ thị truy cập mặc định cho lớp là internal. Còn chỉ thị truy cập mặc định cho các thành viên của lớp là private.
  • data type: xác định kiểu dữ liệu của thuộc tính.
  • return type: xác định kiểu dữ liệu trả về của phương thức, nếu phương thức không trả về dữ liệu thì sử dụng kiểu void.
  • constructor: là phương thức khởi tạo của class. Mặc định khi bạn không khai báo constructor thì khi biên dịch hệ thống sẽ tự tạo một constructor mặc định - là constructor không có đối số.
  • Tên lớp, thuộc tính, phương thức hợp lệ chỉ gồm ký tự a-z, A-Z, số 0-9 và ký tự _ và không được bắt đầu bằng số 0-9. Quy ước đặt tên trong C# bắt đầu bằng ký tự viết hoa A-Z.

Ví dụ sau minh họa các khái niệm được thảo luận ở trên:

using System;

namespace BoxApplication 
{
   class Box 
   {
   	  // properties
      public double Length { get; set; }
      public double Breadth { get; set; }
      public double Height { get; set; }
   }
   
   class Boxtester 
   {
      static void Main(string[] args) 
      {
         Box box = new Box();
         box.Length = 6.0;
         box.Breadth = 7.0;
         box.Height = 5.0;

         Console.WriteLine("Length = {0}, Breadth = {1}, Height = {2}", box.Length, box.Breadth, box.Height);
         Console.ReadKey();
      }
   }
}

Kết quả khi biên dịch và chạy đoạn mã trên:

Length = 6, Breadth = 7, Height = 5

Phương thức trong C#

Phương thức của lớp là một các dòng lệnh để thực hiện một nhiệm vụ nào đó. Nó hoạt động trên bất kỳ đối tượng nào của lớp mà nó là thành viên và có quyền truy cập vào tất cả các thành viên của một lớp cho đối tượng đó.

Chúng ta hãy đặt các khái niệm trên để thiết lập và nhận giá trị của các thành viên lớp khác nhau trong một lớp:

using System;

namespace BoxApplication 
{
   class Box 
   {
   	  // properties
      public double Length { get; set; }
      public double Breadth { get; set; }
      public double Height { get; set; }
            
      // methods
      public void Print()
      {
      	  Console.WriteLine("Length = {0}, Breadth = {1}, Height = {2}", Length, Breadth, Height);
      }
   }
   
   class Boxtester 
   {
      static void Main(string[] args) 
      {
         Box box = new Box();
         box.Length = 6.0;
         box.Breadth = 7.0;
         box.Height = 5.0;
         
         box.Print();         
         Console.ReadKey();
      }
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Length = 6, Breadth = 7, Height = 5

Phương thức khởi tạo trong C#

Phương thức khởi tạo (constructor) là một phương thức đặc biệt của lớp mà nó sẽ được thực thi bất cứ khi nào chúng ta tạo ra các đối tượng mới của lớp đó.

Một constructor có cùng tên với tên của lớp và nó không có bất kỳ kiểu trả về nào. Ví dụ sau giải thích khái niệm về constructor:

using System;

namespace BoxApplication 
{
   class Box 
   {
   	  // properties
      public double Length { get; set; }
      public double Breadth { get; set; }
      public double Height { get; set; }
      
      // default constructor
      public Box()
      {}
      
      // constructor with parameters
      public Box(double length, double breadth, double height)
      {
      	  Length = length;
          Breadth = breadth;
          Height = height;
      }
            
      // methods
      public void Print()
      {
      	  Console.WriteLine("Length = {0}, Breadth = {1}, Height = {2}", Length, Breadth, Height);
      }
   }
   
   class Boxtester 
   {
      static void Main(string[] args) 
      {
         Box box = new Box(6.0, 7.0, 5.0);
         
         box.Print();         
         Console.ReadKey();
      }
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Length = 6, Breadth = 7, Height = 5

Một constructor mặc định không có bất kỳ tham số nào nhưng nếu bạn cần, một phương thức khởi tạo có thể có các tham số.

Các constructor như vậy được gọi là constructor tham số. Kỹ thuật này giúp bạn gán giá trị ban đầu cho một đối tượng tại thời điểm tạo ra nó.

Ngoài ra trong C# còn có 2 loại constructor đặc biệt khác nữa đó là private constructorstatic constructor.

Private constructor trong C#

Private constructor thường được sử dụng cho lớp có các thành viên tĩnh. Nó ngăn không cho khởi tạo đối tượng từ class.

public class Counter
{
    private Counter() { }
    public static int currentCount;
    public static int IncrementCount()
    {
        return ++currentCount;
    }
}

class TestCounter
{
    static void Main()
    {
        // Counter aCounter = new Counter();   // Error
        Counter.currentCount = 100;
        Counter.IncrementCount();
        Console.WriteLine("New count: {0}", Counter.currentCount);
        Console.ReadKey();
    }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

New count: 101

Static constructor trong C#

Static constructor được sử dụng để khởi tạo giá trị cho bất kỳ thành phần static của class hoặc thực hiện một hành động cụ thể nào đó mà chỉ được thực hiện một lần duy nhất.

Nó được gọi thực thi tự động một lần duy nhất ngay khi bất kỳ thành phần static nào của class được gọi.

class SimpleClass
{
    static readonly long baseline;

    static SimpleClass()
    {
        baseline = DateTime.Now.Ticks;
    }
}

Static constructor có một số đặc tính sau:

  • Static constructor không có chỉ thị truy cập và không có đối số.
  • Một class hoặc struct chỉ có một static constructor.
  • Static constructor không thể gọi trực tiếp mà được bộ thực thi gọi tự động.
  • Nếu bạn không cung cấp một static constructor để khởi tạo giá trị cho các trường static thì chúng sẽ được gán giá trị mặc định theo kiểu dữ liệu của chúng.
  • Nếu có ngoại lệ phát sinh trong static constructor thì bộ thực thi sẽ không gọi chúng thêm một lần nào nữa.
  • Một trường được khai báo là static readonly chỉ có thể được gắn giá trị ngay khi khai báo hoặc trong static constructor.

Phương thức hủy trong C#

Phương thức hủy (destructor) là một phương thức đặc biệt của một lớp được thực thi bất cứ khi nào một đối tượng của lớp đó vượt quá phạm vi.

Destructor có cùng tên với tên của lớp có dấu ngã (~) và nó không thể trả về giá trị, không có chỉ thị truy cập cũng như không có bất kỳ tham số nào.

Destructor có thể rất hữu ích để giải phóng tài nguyên bộ nhớ trước khi thoát khỏi chương trình. Phá hủy không thể được thừa kế hoặc quá tải.

Ví dụ sau giải thích khái niệm về destructor:

using System;

namespace LineApplication 
{
   class Line 
   {
      public double Length { get; set; }
      
      public Line() 
      {
         Console.WriteLine("Object is being created");
      }
      
      // destructor
      ~Line() 
      {
         Console.WriteLine("Object is being deleted");
      }
      
      static void Main(string[] args) 
      {
         Line line = new Line();
         line.Length = 6.0;
         Console.WriteLine("Length of line : {0}", line.Length);           
      }
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Object is being created
Length of line : 6
Object is being deleted

Thành viên tĩnh của lớp C#

Chúng ta có thể định nghĩa các thành viên tĩnh của lớp bằng cách sử dụng từ khóa static .

Khi chúng ta khai báo một thành viên của một lớp là tĩnh, điều đó có nghĩa là cho dù có bao nhiêu đối tượng của lớp được tạo ra, chỉ có một bản sao của thành viên tĩnh.

Các biến tĩnh được sử dụng để lưu trữ và chia sẻ giá trị chung giữa tất cả các đối tượng được tạo từ lớp.

Ví dụ sau đây cho thấy việc sử dụng các biến tĩnh:

using System;

namespace StaticVarApplication 
{
   class StaticVar 
   {
      public static int num;
      
      public void count() 
      {
         num++;
      }
      public int getNum() 
      {
         return num;
      }
   }
   
   class StaticTester 
   {
      static void Main(string[] args) 
      {
         StaticVar s1 = new StaticVar();
         StaticVar s2 = new StaticVar();
         
         s1.Count();
         s1.Count();
         s1.Count();
         
         s2.Count();
         s2.Count();
         s2.Count();
         
         Console.WriteLine("Variable num for s1: {0}", s1.GetNum());
         Console.WriteLine("Variable num for s2: {0}", s2.GetNum());
         Console.ReadKey();
      }
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Variable num for s1: 6
Variable num for s2: 6

Bạn cũng có thể khai báo một phương thứcstatic. Các phương thức như vậy chỉ có thể truy cập các biến tĩnh.

Các phương thức tĩnh chỉ có thể truy cập ở cấp độ class, không thể truy cập ở các thể hiện của lớp. Ví dụ sau đây cho thấy việc sử dụng các phương thức tĩnh:

using System;

namespace StaticVarApplication 
{
   class StaticVar 
   {
      public static int num;
      
      public void Count() 
      {
         num++;
      }
      public static int GetNum() 
      {
         return num;
      }
   }
   class StaticTester 
   {
      static void Main(string[] args) 
      {
         StaticVar s = new StaticVar();
         
         s.Count();
         s.Count();
         s.Count();
         
         Console.WriteLine("Variable num: {0}", StaticVar.GetNum());
         Console.ReadKey();
      }
   }
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

Variable num: 3

Partial class trong C#

Mỗi lớp trong C# nằm trong một file vật lý riêng biệt có phần mở rộng .cs. C# cung cấp khả năng thực hiện một lớp duy nhất trong nhiều file .cs bằng cách sử dụng từ khóa partial. Từ khóa partial có thể được áp dụng cho lớp, phương thức, interface hoặc struct.

Ví dụ: lớp MyPartialClass sau đây chia thành hai tệp, MyPartialClass.cs và MyPartialClass.Common.cs:

public partial class MyPartialClass
{
    public MyPartialClass()
    {
    }

    public void Method1(int val)
    {
        Console.WriteLine(val);
    }
}
File MyPartialClass.cs
public partial class MyPartialClass
{
    public void Method2(int val)
    {
        Console.WriteLine(val);
    }
}
File MyPartialClass.Common.cs

Lớp MyPartialClass trong MyPartialClass.cs định nghĩa phương thức khởi tạo và một phương thức public Method1, trong khi MyPartialClass.Common.cs chỉ có một phương thức public là Method2. Trình biên dịch sẽ kết hợp hai phần này thành một lớp như sau:

public class MyPartialClass
{
    public MyPartialClass()
    {
    }
        
    public void Method1(int val)
    {
        Console.WriteLine(val);
    }

    public void Method2(int val)
    {
        Console.WriteLine(val);
    }
}

Yêu cầu của partial class:

  • Tất cả các phần của partial class phải nằm trong cùng một namespace và assembly.
  • Tất cả các phần của partial class phải có cùng chỉ thị truy cập.
  • Nếu bất kỳ phần nào của partial class được khai báo protected, sealed thì lớp sẽ được khai báo như vậy.
  • Chỉ thị partial chỉ có thể xuất hiện ngay trước từ khóa class, struct hoặc interface.

Ưu điểm của partial class

  • Nhiều nhà phát triển có thể làm việc đồng thời với một lớp trong các tệp riêng biệt.
  • Khi làm việc với trình tạo mã nguồn tự động, mã có thể được thêm vào lớp mà không phải tạo lại file nguồn.

Mệt chưa bạn ơi, nếu chưa thì xem tiếp bài này nhé:

Lập trình hướng đối tượng (OOP) trong C# | Comdy
Lập trình hướng đối tượng (OOP) trong C# là gì? 5 khái niệm và 4 tính chất quan trọng của lập trình hướng đối tượng là gì?
Lập Trình C#Lập Trình C# Cơ Bản
Bài Viết Liên Quan:
int[] và int[,] trong C#: Ai nhanh hơn
Trung Nguyen 10/10/2020
int[] và int[,] trong C#: Ai nhanh hơn

Hiểu được sự khác biệt giữa các loại mảng trong C# sẽ giúp bạn chọn cấu trúc dữ liệu chính xác cho mọi trường hợp.

Struct và class trong C#: Ai nhanh hơn
Trung Nguyen 09/10/2020
Struct và class trong C#: Ai nhanh hơn

Trong bài viết này, tôi sẽ so sánh sự khác biệt về hiệu suất giữa struct và class trong C#: Ai nhanh hơn.

Best practice cho performance trong C#
Trung Nguyen 03/10/2020
Best practice cho performance trong C#

Mục tiêu của bài viết này là cung cấp một danh sách không đầy đủ các code mẫu cần tránh, vì chúng rủi ro hoặc performance kém.

Đọc ghi file (File I/O) trong C#
Trung Nguyen 26/04/2020
Đọc ghi file (File I/O) trong C#

Hướng dẫn này sẽ giúp bạn tìm hiểu về đọc ghi file (File I/O) trong C# và sử dụng các lớp tiện ích để đọc ghi file.