C# - C Sharp: Từ khóa static

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Từ khóa static trong C# được sử dụng với mục đích chính là để quản trị bộ nhớ. Ta có thể áp dụng từ khóa static với các trường (cũng được gọi là biến lớp, biến class, trường thể hiện), phương thức (cũng được gọi là phương thức lớp, phương thức thể hiện), lớp. Từ khóa static thuộc về lớp chứ không thuộc về đối tượng (thể hiện) của lớp.

Trường static trong C#

Khi bạn khai báo một trường (field) là static, thì trường đó được gọi là trường tĩnh, hay hay thuộc tính static.

Trường static được sử dụng làm trường chung cho tất cả đối tượng, ví dụ như tên công ty của nhân viên là chung, tên trường học của các sinh viên là chung, …

Lợi thế của trường static

Trường static giúp bộ nhớ chương trình của bạn được sử dụng hiệu quả hơn (tiết kiệm bộ nhớ) vì chỉ có 1 vùng nhớ duy nhất được tạo cho mỗi trường static.

Tìm hiểu vấn đề xảy ra khi không có trường static

public class Student{
  int rollno; //mã sinh viên
  String name; //tên sinh viên
  String college="V1Study"; //tên trường
}

Giả sử có 5000 sinh viên trong trường đại học, thì mỗi sinh viên có rollno và name riêng. Tuy nhiên ở đây, college là thuộc tính chứa tên trường của các đối tượng sinh viên, mà trong ví dụ trên nó chứa "V1Study", thì nếu như khai báo thuộc tính college như ở trên thì sẽ có 5000 vùng nhớ được tạo cho thuộc tính college của 5000 sinh viên, và 5000 vùng nhớ này đều chứa "V1Study", điều này dẫn đến rất lãng phí bộ nhớ. Nhưng nếu như ta thiết lập cho thuộc tính college là static, thì chỉ có duy nhất 1 vùng nhớ được tạo ra và 5000 sinh viên sẽ đều sử dụng chung vùng nhớ này và vì vậy 5000 sinh viên đều có college là "V1Study".

Ghi chú: Các trường static trong C# được chia sẻ tới tất cả các đối tượng, tức tất cả các đối tượng của một lớp sẽ dùng chung các trường static.

Ví dụ về trường static trong C#

Đổi tên trường (college)

namespace Demo1
{
  //Ví dụ về trường static trong C#
  class Student1
  {
    int rollno;
    string name;
    static string college = "V1Study";

    public int Rollno { get => rollno; set => rollno = value; }
    public string Name { get => name; set => name = value; }
    public string College { get => college; set => college = value; }

    public Student1() { }

    public Student1(int rollno, string name)
    {
      this.rollno = rollno;
      this.name = name;
    }

    public void Display()
    {
      Console.WriteLine($"{rollno} - {name} - {college}");
    }
  }

  internal class Static
  {
    static void Main(string[] args)
    {
      Student1 s1 = new Student1(111, "Hoang");
      Student1 s2 = new Student1(222, "Thanh");
      Console.WriteLine("Ten truong ban dau:");
      s1.Display(); //Cả s1
      s2.Display(); //và s2 đều có tên trường là V1Study
      Console.WriteLine("Doi ten truong:");
      s1.College = "V1Study Academy"; //Tiến hành đổi tên trường cho s1
      s1.Display(); //thì cả s1
      s2.Display(); //và s2 đều vẫn có cùng tên trường.
    }
  }
}

Kết quả:

Ten truong ban dau:
111 - Hoang - V1Study
222 - Thanh - V1Study
Doi ten truong:
111 - Hoang - V1Study Academy
222 - Thanh - V1Study Academy

Chương trình Counter không sử dụng trường static

Trong ví dụ sau, ta tạo một trường có tên count và giá trị của nó tăng 1 đơn vị trong hàm tạo. Khi ta tạo các đối tượng thì mỗi đối tượng sẽ có trường count này và đều chứa giá trị là 1.

namespace Demo1
{
  public class Counter
  {
    int count = 0;

    public int Count { get => count; set => count = value; }

    public Counter()
    {
      count++;
    }
  }

  internal class Static
  {
    static void Main(string[] args)
    {
      Counter c1 = new Counter();
      Console.WriteLine($"count cua c1: {c1.Count}");
      Counter c2 = new Counter();
      Console.WriteLine($"count cua c2: {c2.Count}");
      Counter c3 = new Counter();
      Console.WriteLine($"count cua c3: {c3.Count}");
    }
  }
}

Kết quả:

count cua c1: 1
count cua c2: 1
count cua c3: 1

Chương trình Counter dùng static

Bây giờ bạn sửa ví dụ trên bằng cách đặt từ khóa static cho trường count thì khi ta tạo các đối tượng thì các đối tượng này sẽ dùng chung trường count.

namespace Demo1
{
  public class Counter
  {
    static int count = 0;//biến count sẽ là biến dùng chung vì được khai báo là static

    public int Count { get => count; set => count = value; }

    public Counter()
    {
      count++;
    }
  }

  internal class Static
  {
    static void Main(string[] args)
    {
      Counter c1 = new Counter();
      Console.WriteLine($"count cua c1: {c1.Count}");
      Counter c2 = new Counter();
      Console.WriteLine($"count cua c2: {c2.Count}");
      Counter c3 = new Counter();
      Console.WriteLine($"count cua c3: {c3.Count}");
    }
  }
}

Kết quả:

count cua c1: 1
count cua c2: 2
count cua c3: 3

Phương thức static trong C#

Nếu bạn áp dụng từ khóa static với bất cứ phương thức nào, thì phương thức đó được gọi là phương thức static.

  • Một phương thức static sẽ thuộc về lớp chứ không thuộc đối tượng của lớp.
  • Phương thức static có thể được gọi mà không cần phải thông qua đối tượng của lớp.
  • Phương thức static có thể truy cập các thành phần (trường, phương thức) static một cách trực tiếp.

Ví dụ về phương thức static trong C#

//Ví dụ về phương thức static trong C#
namespace Demo1
{
  public class Student1
  {
    int rollno;
    string name;
    static string college = "V1Study";

    public int Rollno { get => rollno; set => rollno = value; }
    public string Name { get => name; set => name = value; }
    public string College { get => college; set => college = value; }

    public Student1(int rollno, string name)
    {
      this.rollno = rollno;
      this.name = name;
    }

    public static void ChangeCollege()
    {//phương thức static
      college = "V1Study Academy";
    }

    public void Display()
    {
      Console.WriteLine($"{rollno} - {name} - {college}");
    }
  }

  internal class Static
  {
    static void Main(string[] args)
    {
      Student1 s1 = new Student1(111, "Hoang");
      Student1 s2 = new Student1(222, "Thanh");
      Console.WriteLine("Before renaming the college:");
      s1.Display();
      s2.Display();
      Student1.ChangeCollege();
      Console.WriteLine("After renaming the college:");
      s1.Display();
      s2.Display();
    }
  }
}

Kết quả:

Before renaming the college:
111 - Hoang - V1Study
222 - Thanh - V1Study
After renaming the college:
111 - Hoang - V1Study Academy
222 - Thanh - V1Study Academy

Ví dụ khác về phương thức static thực hiện phép tính toán thông thường

namespace Demo1
{
  //Chương trình lấy cube (giá trị lập phương) của số đã cho bằng phương thức static
  class Calculate
  {
    internal static long Cube(int x)
    {
      return x * x * x;
    }

  }

  internal class Static
  {
    static void Main(string[] args)
    {
      int x = 5;
      long result = Calculate.Cube(x);
      Console.WriteLine($"{x} * {x} * {x} = {result}");
    }
  }
}

Kết quả:

5 * 5 * 5 = 125

Một số hạn chế đối với phương thức static

Có hai hạn chế chính đối với phương thức static. Đó là:

  • Phương thức static không thể sử dụng được trường non-static hoặc gọi trực tiếp phương thức non-static.
  • Từ khóa this và base không thể được sử dụng trong ngữ cảnh static.

Ví dụ:

public class A {
  int a = 40; //non-static

  static void Main(string args[]) {
    Console.WriteLine(a);//xảy ra lỗi ở đây
  }
}

Chạy chương trình trên sẽ cho lỗi là:

Error CS0120  An object reference is required for the non-static field, method, or property 'A.a'.

Câu hỏi: Tại sao phương thức Main() trong C# là static?

Do không cần phải sử dụng đối tượng để gọi phương thức static nhưng với phương thức non-static thì cần, nên nếu phương thức Main() là phương thức non-static, thì  đầu tiên sẽ phải tạo đối tượng và sau đó gọi phương thức Main(), và điều này có thể gây ra vấn đề về cấp phát bộ nhớ phụ.

Câu hỏi: Ta có thể thực thi một chương trình mà không có phương thức Main()?

Có, bạn có thể làm điều này bằng cách sử dụng C# từ phiên bản 9.

» Tiếp: Thừa kế (Inheritance)
« Trước: Từ khóa this
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!