28 tháng 4, 2020

this và static trong C#

Trong bài học chúng ta sẽ cùng tìm hiểu về 2 từ khóa this static, đây là 2 từ khóa thường xuyên được sử dụng trong quá trình lập trình bằng C#.

this và static

1. This trong C#

Ta cùng xét ví dụ sau:
namespace ConsoleApp10
{
    class People
    {
        private string Name;
        private int ID;
        private int Age;

        public People(string name, int id, int age)
        {
            Name = name;
            ID = id;
            Age = age;
        }

        public void ShowInfo()
        {
            Console.WriteLine("Ho ten: {0}, ID: {1}, tuoi: {2}", Name, ID, Age);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            People P1 = new People("Nguyen Duong", 123456, 26);
            P1.ShowInfo();

            Console.ReadLine();
        }
    }
}

Bạn có để ý thấy, tham số trong hàm People mình cũng đặt là name, id, age có ý nghĩa giống với tên biến của class nhưng được viết thường. Còn tên biến của class thì được viết hoa chữ cái đầu. Làm như vậy hơi bất tiện, nhưng nếu đặt tên tham số trong hàm People giống tên biến của class thì chương trình sẽ không phân biệt được. Vì vậy ta phải dùng đến từ khóa this.
Đoạn code trong hàm People có thể được sửa như sau:
public People(string Name, int ID, int Age)
{
       this.Name = Name;
       this.ID = ID;
       this.Age = Age;
}

Kết quả vẫn ra như đoạn code lúc đầu. 

Bạn có thể click chuột vào biến hoặc tham số của hàm để xem Visual Studio bôi đen những vị trí xuất hiện của chúng.
Rõ ràng là khi mình click chuột vào chữ Name sau this. trùng tên với tham số nhưng Visual không nhầm lẫn với tham số của hàm People.

Từ khóa this trong C# được sử dụng để tham chiếu đến thể hiện (instance) hiện tại của lớp. Nó cũng được sử dụng để phân biệt giữa các tham số phương thức và các dữ liệu thành viên của lớp nếu cả hai đều có cùng tên.

2. Static trong C#

Đôi lúc người lập trình mong muốn 1 thuộc tính hoặc phương thức nào đó được dùng chung cho mọi đối tượng (chỉ cần cấp phát 1 vùng nhớ duy nhất). Vì vậy phải dùng từ khóa static, để khai báo một phần tử tĩnh.

Có 4 loại phần tử tĩnh:
- Biến tĩnh
- Hàm tĩnh
- Lớp tĩnh
- Hàm khởi tạo tĩnh

2.1: Biến tĩnh

- Biến tĩnh biến dùng chung cho mọi đối tượng thuộc lớp.
- Nó được khởi tạo vùng nhớ 1 lần duy nhất ngay khi chương trình được nạp vào bộ nhớ để thực thi và huỷ khi kết thúc chương trình.

Cú pháp:
<phạm vi truy cập> static <kiểu dữ liệu> <tên biến> = <giá trị khởi tạo>;

Xét ví dụ sau:
public class BlackCat
{
       public double Weight;
       public double Height;
       public string Color = "Mau den";
}

Ta có lớp BlackCat có 3 thuộc tính là Weight, HeightColor. Với Color luôn là màu đen. Nếu khai báo như trên thì cứ với mỗi biến chương trình phải cấp phát 3 vùng nhớ trong khi thuộc tính màu đen là đặc điểm chung của lớp mèo đen. Với từ khóa static thì chương trình chỉ cấp phát 1 vùng nhớ duy nhất cho thuộc tính Color.

Ví dụ tính số lượng mèo được tạo ra.
Ý tưởng: Khởi tạo biến đếm trong lớp mèo, cứ mỗi lần tham số thuộc tính được truyền vào thì tăng biến đếm lên một đơn vị.
namespace ConsoleApp9
{
    public class BlackCat
    {
        public double Weight;
        public double Height;
        public static string Color = "Mau den";
        public static int CountCat = 0;
        public BlackCat(double Weight, double Height)
        {
            this.Weight = Weight;
            this.Height = Height;
            CountCat++;
        }
        public void ShowInfo()
        {
            Console.WriteLine("{0}, {1} kg, {2} cm ", Color, Weight, Height);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("so luong meo hien tai là: " + BlackCat.CountCat);
            BlackCat BlackCat1 = new BlackCat(2.2, 20);
            BlackCat1.ShowInfo();
            Console.WriteLine("so luong meo hien tai là: " + BlackCat.CountCat);

            BlackCat BlackCat2 = new BlackCat(2.6, 25);
            BlackCat2.ShowInfo();
            Console.WriteLine("so luong meo hien tai là: " + BlackCat.CountCat);

            BlackCat BlackCat3 = new BlackCat(2.3, 25);
            BlackCat3.ShowInfo();
            Console.WriteLine("so luong meo hien tai là: " + BlackCat.CountCat);

            BlackCat BlackCat4 = new BlackCat(2.4, 26);
            BlackCat4.ShowInfo();
            Console.WriteLine("so luong meo hien tai là: " + BlackCat.CountCat);

            BlackCat BlackCat5 = new BlackCat(2.7, 26);
            BlackCat5.ShowInfo();
            Console.WriteLine("so luong meo hien tai là: " + BlackCat.CountCat);

            Console.ReadLine();
        }
    }
}

Kết quả

Ví dụ: Thay đổi thuộc tính Color từ Mau den thành Mau long den
BlackCat.Color = "Mau long den";

BlackCat BlackCat6 = new BlackCat(2.7, 26);
BlackCat6.ShowInfo();
Console.WriteLine("so luong meo hien tai là: " + BlackCat.CountCat);

2.2: Hàm tĩnh

- Hàm tĩnh là 1 hàm dùng chung của lớp. Được gọi thông qua tên lớp và không cần khởi tạo bất kỳ đối tượng nào, từ đó tránh việc lãng phí bộ nhớ.
- Hỗ trợ trong việc viết các hàm tiện ích để sử dụng lại.

Cú pháp:
<phạm vi truy cập> static <kiểu trả về> <tên hàm>
{
           // nội dung
}

Cách sử dụng thì thao tác hoàn toàn giống 1 hàm bình thường chỉ cần lưu ý là phải gọi thông qua tên lớp.

Ví dụ:
namespace ConsoleApp11
{
    class tinhtoan
    {
        public static int tong (int a, int b)
        {
            return a + b;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("tong 2 so là: " + tinhtoan.tong(3, 3));

            Console.ReadLine();
        }
    }
}

2.3: Lớp tĩnh

- Lớp tĩnh chỉ chứa các thành phần tĩnh (biến tĩnh, hàm tĩnh).
- Không thể khai báo, khởi tạo 1 đối tượng thuộc lớp tĩnh.

Nhìn lại ví dụ trên trong mục hàm tĩnh, mĩnh đã tạo ra một class tính toán với 1 hàm tính tổng. Rõ ràng đây là một tiện ích sẽ được dùng đi dùng lại nhiều với mục đích tính tổng 2 số nguyên. Nhưng để class bình thường như vậy thì chẳng may sẽ có người dùng vô ý tạo ra đối tượng mới, mặc dù chả có ý nghĩa gì. Để tránh tình trạng này, ta cần thêm từ khóa static khi khai báo class.
public static class tinhtoan
{
        public static int tong (int a, int b)
        {
            return a + b;
        }
}

Trong C# có hỗ trợ chúng ta rất nhiều lớp tiện ích dạng lớp tĩnh, phương thức tĩnh. Ví dụ như lớp Math, bạn có thể gõ Math. rồi tự nghịch ngợm, khám phá nhé.

2.4: Hàm khởi tạo tĩnh

Cú pháp:
static <tên lớp>()
{
      // nội dung
}

Lưu ý
- Không được phép khai báo phạm vi truy cập. Nếu cố tình làm điều này C# sẽ báo lỗi khi biên dịch.
- Hàm khởi tạo tĩnh sẽ được gọi 1 lần duy nhất khi chương trình được nạp vào bộ nhớ để thực thi như là 1 cách để ta thiết lập một số thông số theo ý muốn trước khi có bất kỳ đối tượng nào được tạo ra.
- Không thể gọi các thuộc tính không phải static.

Ví dụ
namespace ConsoleApp11
{
    public static class WhiteCat
    {
        public static string MauLong;
        static WhiteCat()
        {
            MauLong = "Mau trang";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {           
            Console.WriteLine(WhiteCat.MauLong);
         
            Console.ReadLine();
        }
    }
}

Nếu biến MauLong mình không để static thì hàm khởi tạo không thể gọi được. Các bạn thử xóa chữ static ở dòng khai báo biến đi, hệ thống sẽ báo lỗi. 

SHARE THIS

Blogger Nguyễn Dương

Có một câu nói mà mình rất thích đó là "Thật sai lầm khi nghĩ rằng một khi rời khỏi trường học, bạn không cần học thêm điều mới nữa". Chính vì thế mà hãy luôn luôn học hỏi, con người chỉ ngừng phát triển khi ngừng học hỏi. Nếu như bạn chưa hiểu nội dung bài viết hoặc đang khúc mắc khi thao tác thì hãy bình luận phía dưới bài viết để mọi người cùng thảo luận nhé!