Static trong C#

C# có từ khóa static giống như các ngôn ngữ lập trình khác như C ++, Java, v.v ... Từ khóa static có thể được áp dụng trên lớp, trường, phương thức, thuộc tính, toán tử, sự kiện và phương thức khởi tạo. Tuy nhiên, nó không thể được sử dụng với các bộ chỉ mục (indexers), phương thức hủy hoặc các kiểu dữ liệu khác ngoài lớp.

Chỉ thị static làm cho một thành phần không thể khởi tạo được, điều đó có nghĩa là thành phần tĩnh không thể được khởi tạo.

Nếu chỉ thị static được áp dụng cho một lớp thì lớp đó không thể khởi tạo thể hiện bằng từ khóa new.

Nếu chỉ thị static được áp dụng cho một trường, phương thức hoặc thuộc tính của lớp thì chúng không thể được truy cập từ đối tượng thể hiện của lớp, mà chỉ có thể truy cập ở cấp độ lớp bằng cú pháp sau ClassName.PropertyName, ClassName.MethodName.

Hãy xem ví dụ sau về lớp tĩnh (static class) trong C#:

public static class MyStaticClass
{
    public static int myStaticVariable = 0;

    public static void MyStaticMethod()
    {
        Console.WriteLine("This is a static method.");
    }

    public static int MyStaticProperty { get; set; }
}

class Program
{
    static void Main(string[] args)
    {        
        Console.WriteLine(MyStaticClass.myStaticVariable);
        MyStaticClass.MyStaticMethod();
        MyStaticClass.MyStaticProperty = 100;
        Console.WriteLine(MyStaticClass.MyStaticProperty);
    }
}
Lớp tĩnh (static class) trong C#

Đây là kết quả khi biên dịch và chạy chương trình:

0
This is a static method.
100

Trong ví dụ trên, MyStaticClass là một lớp tĩnh với trường, phương thức và thuộc tính tĩnh.  Tất cả các thành viên tĩnh chỉ có thể được truy cập từ cấp độ lớp, ví dụ MyStaticClass.MyStaticMethod().

Một lớp bình thường (lớp không tĩnh) cũng có thể có các thành viên tĩnh. Bạn có thể khởi tạo các lớp không tĩnh bằng cách sử dụng từ khóa new như bình thường.

Tuy nhiên, biến đối tượng chỉ có thể truy cập các trường, thuộc tính và phương thức không tĩnh, nó không thể truy cập các phương thức và biến tĩnh. Tất cả các thành viên tĩnh chỉ có thể truy cập ở cấp độ lớp.

Tips: Phương thức tĩnh chỉ có thể truy cập các thành viên tĩnh khác.

Ví dụ: hãy xem xét lớp MyNonStaticClass sau đây với sự pha trộn của các phương thức tĩnh và không tĩnh:

public class MyNonStaticClass
{
    private static int myStaticVariable = 0;

    public static void MyStaticMethod()
    {
        Console.WriteLine("This is static method.");
    }

    public void MyNonStaticMethod()
    {
        Console.WriteLine("Non-static method");
    }
}
Thành viên tĩnh (static member) trong lớp không tĩnh trong C#

Trong ví dụ trên, MyNonStaticClass có thể được khởi tạo và truy cập các thành viên không tĩnh. Tuy nhiên, bạn không thể truy cập các thành viên tĩnh từ đối tượng được khởi tạo từ lớp.

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

Một lớp tĩnh hoặc không tĩnh có thể có một phương thức khởi tạo tĩnh (static constructor) mà không có bất kỳ chỉ thị truy cập nào như public, private, protected, v.v.

Một phương thức khởi tạo tĩnh trong một lớp không tĩnh chỉ chạy một lần khi lớp được khởi tạo lần đầu tiên.

Một phương thức khởi tạo tĩnh trong một lớp tĩnh chỉ chạy một lần khi bất kỳ thành viên tĩnh nào của nó được truy cập lần đầu tiên.

public static class MyStaticClass
{
    public static int myStaticVariable = 0;
    public static int MyStaticProperty { get; set; }
    
    static MyStaticClass()
    {
        Console.WriteLine("Inside static constructor.");
    }

    public static void MyStaticMethod()
    {
        Console.WriteLine("This is static method.");
    }
}

class Program
{
    static void Main(string[] args)
    {        
        MyStaticClass.myStaticVariable = 100;
        MyStaticClass.MyStaticProperty = 200;
        MyStaticClass.myStaticVariable = 300;
        MyStaticClass.MyStaticProperty = 400;
    }
}
Phương thức khởi tạo tĩnh (static constructor) trong lớp tĩnh trong C#

Đây là kết quả khi biên dịch và chạy chương trình:

Inside static constructor.

Trong ví dụ trên, các thành viên tĩnh được truy cập nhiều lần. Tuy nhiên, phương thức khởi tạo tĩnh chỉ được gọi một lần khi bất kỳ thành viên tĩnh nào được truy cập lần đầu tiên.

public class MyNonStaticClass
{
    static MyNonStaticClass()
    {
        Console.WriteLine("Inside static constructor.");
    }
            
    public void MyNonStaticMethod()
    {
        Console.WriteLine("Non-static method");
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyNonStaticClass mnsObj1 = new MyNonStaticClass();
        MyNonStaticClass mnsObj2 = new MyNonStaticClass();
        MyNonStaticClass mnsObj3 = new MyNonStaticClass();
    }
}
Phương thức khởi tạo tĩnh (static constructor) trong một lớp không tĩnh

Đây là kết quả khi biên dịch và chạy chương trình:

Inside static constructor

Trong ví dụ trên, chúng tôi khởi tạo MyNonStaticClass ba lần nhưng hàm tạo tĩnh chỉ được gọi một lần khi nó khởi tạo lần đầu tiên.

Phân bổ bộ nhớ cho các thành phần tĩnh

Như bạn đã biết, bộ nhớ của ứng dụng trong C# là stack và heap. Các thành viên tĩnh được lưu trữ trong một khu vực đặc biệt bên trong heap gọi là heap tần số cao (high frequency heap).

Các thành viên tĩnh của lớp không tĩnh cũng được lưu trữ trong heap và được chia sẻ trên tất cả các thể hiện của lớp. Vì vậy, những thay đổi được thực hiện bởi một thể hiện sẽ được phản ánh trong tất cả các thể hiện khác của lớp.

Như đã đề cập ở trên, một thành viên tĩnh chỉ có thể chứa hoặc truy cập các thành viên tĩnh khác, bởi vì các thành viên tĩnh được gọi mà không tạo một thể hiện và vì vậy chúng không thể truy cập các thành viên không tĩnh.

Hình ảnh sau đây minh họa cách các thành viên tĩnh được lưu trữ trong bộ nhớ:

Những điểm cần nhớ:

  • Các lớp tĩnh không thể được khởi tạo bằng từ khóa new.
  • Các thành phần tĩnh chỉ có thể truy cập các thành phần tĩnh khác. Ví dụ, một lớp tĩnh chỉ có thể chứa các thành viên tĩnh. Một phương thức tĩnh chỉ có thể truy cập các mục tĩnh khác.
  • Các thành phần tĩnh chia sẻ tài nguyên giữa nhiều người dùng.
  • Chỉ thị static không được sử dụng với các bộ chỉ mục (indexers), phương thức hủy hoặc các kiểu dữ liệu khác ngoài lớp.
  • Một phương thức khởi tạo tĩnh trong một lớp không tĩnh chỉ chạy một lần khi lớp được khởi tạo lần đầu tiên.
  • Một phương thức khởi tạo tĩnh trong một lớp tĩnh chỉ chạy một lần khi bất kỳ thành viên tĩnh nào của nó được truy cập lần đầu tiên.
  • Các thành viên tĩnh được phân bổ trong vùng heap tần số cao (high frequency heap) của bộ nhớ.
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.