C# - C Sharp: Từ khóa static
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.
Giải phóng thời gian, khai phóng năng lực