Các hiểu biết cơ bản về C#

Tram Ho

1. Quản lý bộ nhớ (Memory Management)

Để đi sâu vào quản lý bộ nhớ thì các bạn nên hiểu những gì xảy ra bên trong ứng dụng .Net khi ta khai báo biến. Khi bạn khai báo biến thì biến đó sẽ được cấp phát một vài phần(gọi là chunk) của bộ nhớ(memory) trong ram, bộ nhớ này có 3 thứ bên trong: kiểu dữ liệu, giá trị, tên biến.

Hình ảnh trên giải thích những gì xảy ra trong bộ nhớ khi khai báo biến và quan trọng nhất là kiểu dữ liệu của biến để bộ nhớ của biến sẽ đc cấp phát trên bộ nhớ stack hoặc heap.

  • Stack:
    • Là một cấu trúc LIFO(Last-in-first-out), nghĩa là biến nào vào sau thì phải ra trước(tức là sử dụng cái biến vào sau, rồi giải phóng nó(biến nào không đc sd thì cũng bị vứt đi) thì mới sử dụng biến đã đc thêm trước đó vào stack, các biến này mình đang nói là chúng cùng thuộc một phương thức).
    • Các biến đc cấp phát bộ nhớ trên stack thì lưu trữ trực tiếp giá trị của chúng trong bộ nhớ và truy cập biến này thì rất là nhanh, nó đc cấp phát bộ nhớ khi chương trình biên dịch.
  • Heap: Các biến là đc cấp phát bộ nhớ theo một thứ tự ngẫu nhiên và bạn có thể truy xuất nó vào bất kì lúc nào bạn muốn, sau đó nó sẽ đc giải phóng bởi garbage collector khi bạn ko sử dụng nó nữa, chúng đc cấp phát bộ nhớ trên heap tại quá trình runtime và truy cập các biến này thì lâu hơn so với các biến trên stack.
  • Tham khảo ví dụ chi tiết ở đây, đây, đâyđây!

2. Class

  • Class chỉ được thừa kế từ 1 class khác or thừa kế 1 hay nhiều interface.
  • Class đc khai báo trực tiếp bên trong 1 namespace và có cấp độ tiếp cận là public or internal, mặc định là internal.
  • Các thành viên của Class bao gồm cả class đc lồng có sẽ có 1 trong 6 cấp độ tiếp cận đc trình bày ở dưới, mặc định cho các thành viên trong class là private.
  • Lớp chung (Generic Classes) dùng để đóng gói các hoạt động (method), các trường, thuộc tính cùng thuộc về bất kì kiểu dữ liệu nào(tức là chúng ko dành riêng cho bất kì kiểu dữ liệu nào). Thường được sử dụng vs các collections như: lists, hash tables, stacks, queues, trees… đọc thêm ở đâyđây!
  • Một class có thể chứa các khai báo sau:
    1. Constructor, Finalizers(Còn đc gọi là Destructor): Được trình bày ở dưới.
    2. Constants: Là một giá trị immutable (ko thể thay đổi) và chỉ có các kiểu tích hợp (Tức là các kiểu có sẵn trong C# ngoại trừ kiểu object) đc khai báo là hằng số và phải đc khởi tạo khi khai báo.
    3. Fields(trường):
      • Là biến thuộc bất kì kiểu dữ liệu nào và đc khai báo trực tiếp bên trong class hoặc struct. Ví dụ: private DateTime date;
      • Các trường này thường có cấp độ tiếp cận là private hoặc protected, dữ liệu của chúng có thể đc truy xuất thông qua thuộc tính hoặc phương thức hoặc Indexers. Dữ liệu của trường private đc truy xuất bởi thuộc tính public thì trường đó đc gọi là backing store or backing field (trường sao lưu).
    4. Methods
    5. Properties:
      • Dùng để đọc, viết hoặc tính toán giá trị của các trường private nên properties còn đc gọi là accessor, trong accessor có get{} dùng để đọc dữ liệu, set{} dùng để thiết lập giá trị và get{}, set{} còn đc gọi là “property accessor” đôi khi ta gọi từng cái là accessor cũng đc.
      • Auto-Implemented Properties (Thuộc tính tự động triển khai): Là thuộc tính mà ta ko có bất cứ xử lý nào (tức ko có đoạn code nào) trong get{} và set{}, làm cho khai báo thuộc tính nó ngắn gọn hơn, có từ bản C# 3.0 và cao hơn. Thuộc tình này bắt buộc phải có accessor get{}. Ví dụ: public string Name { get; set; }
      • Thuộc tính tự động triển khai đc khai báo như ví dụ trên thì trình biên dịch sẽ tạo trường sao lưu (backing field) private và ẩn danh, trường này chỉ có thể truy cập qua accessor get{}, set{}. Trong bản C# 6.0 thì thuộc tính này có thể đc gán giá trị khi khai báo. Ví dụ: public string Name { get; set; } = “cuong”;
    6. Indexer: Cho phép đối tượng của class hoặc struct đc lập chỉ mục giống như mảng (Hiểu nôm na thì đối tượng đó giống như một mảng), indexer nó gần giống với thuộc tính ngoại trừ thằng Indexer nó có tham số và sử dụng tham chiếu this thay cho tên của Indexer.
    7. Operators (toán tử): Ví dụ: +, -, *, /….
    8. Events (Sự kiện): Sự kiện cho phép 1 class or object thông báo đến class or đối tượng khác về hành động nào đấy mà class or đối tượng khác đó đang quan tâm đã đc xảy ra để thực hiện các tác vụ xử lý gì đấy. Class mà gửi ( or gây ra (raises)) sự kiện thì đc gọi là publisher và class nhận (or xử lý(handle)) sự kiện đó đc gọi là subscribers. Sự kiện thường đc sử dụng trong window form hay trong các ứng dụng web, đọc thêm ở đây!
    9. Classes: Trong C# bạn đc phép định nghĩa một class bên trong class khác, đọc thêm ở đây!
    10. Interfaces: Dc phép khai báo trong class và ít khi đc khai báo trong class , đa số interface đc khai báo ở bên ngoài class.
    11. Delegates, Structure types, Enumeration types: Đc trình bày ở dưới.
  • Chương trình minh họa class trong C#:

3. Quy tắc đặt tên

  • Các quy tắc đặt tên sau áp dụng hầu hết cho mọi thành phần có tên trong C# như: interface, class, method, field, properties,….
    • Các kí tự đc cho phép là: [A-Z], [a-z], [0-9]), _ (underscore)
    • Tên ko đc bắt đầu bằng số, chỉ có thể bắt đầu bằng chữ hoặc dấu gạch dưới và không đc chứa dấu cách.
    • Không đc sử dụng từ khóa làm tên, nếu sử dụng thì phải thêm tiền tố “@” phía trc từ khóa. Ví dụ: @if
    • Tên trong C# là phân biệt chữ khoa vs chữ thường, tên ko đc chứa 2 dấu gạch dưới.
    • Tên có số kí tự không vượt quá 512 kí tự.

4. Accessibility Levels (Cấp độ tiếp cận)

  • Sử dụng các Access Modifiers (public, protected, internal, or private) để chỉ rõ cấp độ tiếp cận cho các thành viên của class.
    public: Không giới hạn truy cập.
    internal: Có thể truy cập đc từ bất kì đâu trong một assembly.
    private: Quyền truy cập bị giới hạn ở trong lớp hiện tại.
    private protected: Quyền truy cập là trong lớp hiện tại(lớp cơ sở) và lớp dẫn xuất và phải trong một assembly.
    protected: Quyền truy cập bị giới hạn ở trong lớp cơ sở(lớp cha) và lớp dẫn xuất(lớp con).
    protected internal: Quyền truy cập giới hạn trong 1 assembly(Hiểu cơ bản thì nó giới hạn trong một file .cs) và có thể được truy cập bên trong lớp dẫn xuất( lớp kế thừa) trong assembly khác. (Đọc thêm về assembly trong .Net ở đây, đâyđây).
  • Tham khảo ở đâyđây!

5. Data Types

5.1 – Kiểu giá trị (Value Types)

  • Định nghĩa: Các biến có kiểu này thì nó trực tiếp lưu trữ giá trị dữ liệu của nó trong không gian bộ nhớ của chính nó và hầu như nó đc cấp phát(tức lưu trữ) trên stack(Hầu như là vì: Nếu struct được tạo ra là biến local trong 1 hàm thì mới được lưu trữ trên stack, trong các trường hợp khác struct vẫn lưu trữ trong heap, đọc rõ hơn ở đây). Lớp dẫn xuất cho kiểu dữ liệu này là: System.ValueType.
  • Minh họa: Ta có một biến int i = 100 thì hệ thống sẽ lưu trữ 100 trong không gian bộ nhớ được cấp cho biến i( Việc cấp phát bộ nhớ này là do thằng CLR đảm nhiệm, đọc ở đâyđây). Hình ảnh sau minh họa rõ hơn cách mà 100 đc lưu trữ tại vị trí giả định trong memory của ram.
  • Kiểu giá trị lại đc chia thành các kiểu khác:
    • Kiểu đơn giản(Simple type):
      • Signed integral: sbyte, short, int, long
      • Unsigned integral: byte, ushort, uint, ulong
      • Unicode characters: char
      • IEEE binary floating-point: float, double
      • High-precision decimal floating-point: decimal
      • Boolean: bool
    • Kiểu liệt kê (Enum type or enumeration type): Kiểu được xác định bởi một tập hợp các hằng số đc đặt tên( tên này ko đc chứa số) thuộc kiểu số nguyên(integral numeric types – Hiểu nôm na thì kiểu số nguyên là chỉ một số nguyên và số này có thể thuộc nhiều kiểu nguyên như: int, byte, long…), các hằng số này có giá trị kiểu int mặc định là 0, 1… lần lượt tương ứng (đọc thêm đầy đủ chi tiết ở đây, đâyđây!) :
      • Kiểu do người dùng định nghĩa theo mẫu: enum Ten_Enum {…}
    • Kiểu cấu trúc ( structure type or Struct types):
      • Dùng để đóng gói dữ liệu và các chức năng liên quan (nó gần giống với class mình sẽ nói rõ sự khác nhau giữa hai thằng này ở phía dưới), một structure có thể chứa: constructors, constants, fields, methods, properties, indexers and events etc.
      • Cú pháp:
      • Bạn có thể copy đối tượng kiểu cấu trúc sang cho một đối tượng cấu trúc khác khi sử dụng toán tử gán “=”.
      • Lồng cấu trúc (Nesting of Structures): Cấu trúc A lồng cấu trúc B khi bạn tạo đối tượng B trong body của A thì khi đó các đối tượng của A sẽ có cả thành phần dữ liệu của cả A và B nhưng truy cập các thành phần đó của A khác với B (đọc thêm ở đây!).
    • Kiểu giá trị Nullable (Nullable Value Type):
      • Trong C#, bạn không đc gán một giá trị null cho một biến, nhưng từ C# bản 2.0 trở lên thì cho phép bạn gán 1 giá trị null đến một biến được gọi là kiểu nullable, kiểu này làm việc với kiểu đơn giản (Simple Type) của kiểu giá trị, C# bản 8.0 trở lên thì cũng hỗ trợ nullable cho kiểu tham chiếu.
      • Bất kì biến nào có kiểu đơn giản là nullable thì nó là một instance (sự thể hiện hay hiểu nôm na nó giống như đối tượng của class) của cấu trúc(structure) System.Nullable<T>.
      • Cú pháp:
      • Gía trị mặc định cho các biến kiểu nullable là null và bạn có thế gán giá trị của biến non-nullable đến biến nullable tương tứng (tức là cả 2 biến này phải cùng kiểu đơn giản), ví dụ:
  • Truyền các biến có kiểu là value type: Khi bạn truyền biến này cho phương thức nào đấy ( mình gọi là phương thức B), thì biến đó đc tạo bản sao rồi bản sao đó đc truyền cho B và khi bạn thay đổi giá trị của biến đc truyền vào B thì bạn đang thay đổi và làm việc trên bản sao chứ ko phải bản gốc của biến đc truyền vào.

5.2 – Kiểu tham chiếu (Reference types)

  • Định nghĩa: Kiểu tham chiếu (Reference types) thì không trực tiếp lưu trữ giá trị của nó mà nó sẽ lưu trữ địa chỉ nơi mà giá trị đang đc lưu trữ (Nói theo cách: một biến kiểu tham chiếu chứa một con trỏ (pointer) trỏ đến vị trí bộ nhớ khác đang lưu trữ dữ liệu), giá trị các biến kiểu tham chiếu này đc lưu trữ trên bộ nhớ heap.
  • Minh họa: Ta có 1 biến: string s = “Hello World!!”, hình ánh sau đây cho thấy cách mà hệ thống cấp phát bộ nhớ cho biến trên (hệ thống sẽ chọn vị trí bộ nhớ ngẫu nhiên trong ram cho biến s, giá trị của biến s này đc lưu trên stack và nó là một địa chỉ bộ nhớ của nơi đang đc lưu trữ giá trị và giá trị này đc lưu trữ trên heap, đọc thêm ở đây!).
  • Kiểu tham chiếu đc chia thành:
    • Kiểu lớp (Class Types):
      • object: Kiểu object là bí danh của System.Object nên bạn có thể sử dụng System.Object thay cho object và ngc lại. Trong C#, tất cả kiểu người dùng định nghĩa, kiểu tham chiếu, kiểu giá trị đều thừa kế trực tiếp hoặc gián tiếp từ System.Object nên bạn có gán bất kì giá trị nào(chuỗi, số…) đến object. Trước khi gán giá trị thuộc kiểu lớp cho biến khác thì cần phải chuyển đổi kiểu, khi 1 biến kiểu giá trị đc chuyển đổi thành object thì đc gọi là boxing, ngược lại là unboxing.
      • Chuỗi kí tự Unicode (Tên lớp là System.String): string
      • Kiểu đc người dùng định nghĩa theo mẫu: class tenClass {…}
    • Interface types:
      • Kiểu do người dùng định nghĩa theo mẫu: interface tenInterface {…}
    • Kiểu mảng (Array Types):
      • Mảng một chiều hay đa chiều: int[] and int[,]…
      • Được sử dụng làm kiểu trả về của method hoặc dùng để đặt kiểu cho biến, đọc thêm ở đâyđây!.
    • Kiểu ủy nhiệm (Deleate Types):
      • Delegate là một đối tượng tham chiếu đến một phương thức hoặc bạn cũng có thể nói delegate là một biến kiểu tham chiếu giữ một tham chiếu đến bất kỳ phương thức nào mà cùng signature(các tham số cũng như kiểu trả về phải giống nhau) với delegate.
      • Khai báo một kiểu delegate giống như bạn đang định nghĩa một method signature, đó là có giá trị trả về và các tham số.
      • Delegate thường được sử dụng trong xử lý sự kiện hoặc thực thi hàm callback (Callback là một hàm đc truyền dưới dạng 1 đối số (argument) đến một phương thức khác, để tạo callback trong c# thì bạn cần lưu trữ địa chỉ hàm trong một biến bằng việc sử dụng delegate hoặc sử dụng lambda Func or Action).
      • Cú pháp:
      • Tham khảo ở đây, đâyđây!
    • Kiểu Tuple:
      • Tuple là một kiểu dữ liệu có cấu trúc chứa nhiều giá trị của nhiều kiểu khác nhau và tuple không cho phép định nghĩa phương thức trong tuple. (Một biến kiểu tuple nó giống như đối tượng của lớp chỉ có các field). Ví dụ:
      • Tuple còn được sử dụng trong các phương thức khi bạn muốn trả về nhiều giá trị mà không sử dụng các tham số ref hoặc out (tức là kiểu trả về cho phương thức là tuple), sử dụng khi bạn cần truyền nhiều giá trị cho method thông qua một tham số.
      • Bạn có thể sử dụng tuple thay cho kiểu ẩn danh (anonymous types) trong truy vấn LINQ và trong các trường hợp khác.
      • Các phần tử trong tuple có thể trùng nhau và tuple giới hạn 8 phần tử trong nó, nếu muốn có nhiều phần tử thì phải sử dụng tuple lồng nhau, dễ gây loạn lắm nên ae cẩn thận.
      • Tuple là kiểu tham chiếu và đc cấp phát bộ nhớ trên heap do đó trong chương trình mà sử dụng nhiều đến Tuple thì sẽ ảnh hưởng đến CPU (tức là tăng hoạt động của CPU).
      • Tham khảo ở đây, đâyđây!.
  • Truyền biến kiểu tham chiếu: Khi bạn truyền biến kiểu này (gọi là x) đến một phương thức (gọi là B), thì biến x này ko đc tạo bản sao để truyền cho B mà truyền trực tiếp địa chỉ của x cho B, nên khi ở B bạn thay đổi giá trị thực của tham số(tham số này nhận giá trị tuyền vào từ x) tức là bạn đang thay đổi giá trị thực của x. ví dụ:
    Giải thích: Khi bạn truyền đối tượng std1 đến phương thức ChangeReferenceType, thực chất là bạn đang truyền địa chỉ bộ nhớ của sdt1 cho phương thức(tức là đang truyền cho std2) nên trong phương thức đó các bạn thay đổi trên std2 tức là đang thay đổi trên std1 vì cả std1 và std2 đều trỏ đến địa chỉ bộ nhớ của std1.
  • Giá trị mặc định cho các biến kiểu tham chiếu là null(tức là ko tham chiếu đến bất kì đối tượng nào) khi chúng không đc khởi tạo( tức là ko đc gán giá trị). Kiểu giá trị (value types) không đc null, ngoại trừ các biến kiểu giá trị có thể null.

6. Sự khác nhau giữa Class và Struct

ClassStruct
Class là kiểu tham chiếu nên đc cấp phát bộ nhớ trên heap(Tức là các đối tượng của class đc tạo trên bộ nhớ heap) và thường đc sử dụng trong các chương trình lớnStruct là kiểu giá trị nên đc cấp phát bộ nhớ trên stack(Tức là các đối tượng của struct đc tạo trên bộ nhớ stack) và thường đc sd trong các chương trình nhỏ.
Có chứa Constructor, destrcutorKo chứa destructor và constructor ko có tham số, chỉ có constructor có tham số và constructor tĩnh là đc cho phép
Sử dụng từ khóa new để tạo đối tượngCó thể tạo đối tượng mà ko cần từ khóa new
Class có thể thừa kế từ 1class và 1 hay nhiều interfaceKo cho phép thừa kế struct or class khác nhưng có thể thừa kế từ 1 hay nhiều interface
Các thành viên của class có thể là protectedKhông
Các hàm trong class có thể là virtual or abstractKhông

7. Constructor và Destructor

7.1 – Hàm tạo (Constructor)

  • Constructor (hàm tạo): là một hàm chuyên được dùng để gán giá trị cho các field, thuộc tính mỗi khi tạo đối tượng với từ khóa new. Hàm tạo này có tên trùng với tên class của hàm tạo.
  • Một vài quy tắc liên quan đến hàm tạo:
    • Một class mà không có hàm tạo thì sẽ có một hàm tạo mặc định đc tạo bởi trình biên dịch (Hàm tạo mặc định là hàm tạo không có tham số) để gán các giá trị mặc định cho các field, thuộc tính, cụ thể, khởi tạo giá trị cho tất cả các biến thuộc kiểu số(numeric)như: int, double… là số 0, các string và object đc gán null.
    • Hàm tạo có cấp độ truy cập là public thì cho phép ta tạo một object trong assembly hiện tại hoặc assembly tham chiếu (tạo đc object trong một file .cs khác trong project, nếu là private or protected thì sẽ báo lỗi khi tạo đối tượng ở file .cs khác).
    • Hàm tạo có một hoặc nhiều tham số.
    • Một class có thể có nhiều hàm tạo, hàm tạo này phải có tham số khác nhau (số lượng tham số hoặc kiểu của tham số khác nhau khi 2 hay nhiều hàm tạo có số lượng tham số bằng nhau).
    • Hàm tạo không trả về giá trị nào (kiểu void).
    • Đọc thêm về hàm tạo ở đây!
  • Static Constructor:
    • Constructor tĩnh thường được sử dụng để khởi tạo các dữ liệu tĩnh, hoặc thực hiện một chức năng nào đấy mà bạn chỉ muốn thực hiện một lần. Constructor tĩnh này tự động đc gọi (đc thực thi) trước khi cái instance( hiểu là đối tượng) đầu tiên đc tạo hoặc các thành viên tĩnh đc tham chiếu(tức là biến đó đc bạn sử dụng) và nó cũng đc thực thi trước cả constructor ko tĩnh. Ví dụ:
    • Một vài chú ý liên quan đến constructor tĩnh:
      • Không có access modifier (cấp độ truy cập) và không có tham số.
      • Class or struct chỉ có một constructor tĩnh.
      • Không được thừa kế hoặc overloaded (bị ghi đè).
      • Không được gọi trực tiếp mà nó sẽ tự động được gọi bởi CLR.
      • Với các trường tĩnh(thuộc tính) mà bạn ko cung cấp contructor tĩnh để khởi tạo giá trị cho biến tĩnh đó thì các biến đó sẽ đc gán giá trị mặc định (Vào đâyđây để xem giá trị mặc định của từng kiểu nhé!).
      • Các thuộc tính mà bạn khai báo là: static readonly thì chỉ đc gán giá trị trong constructor tĩnh hoặc lúc khai báo( tức là khởi tạo). Và các thuộc tính đó nên đc khởi tạo tại khai báo thay vì trong constructor tĩnh để quá trình runtime đc tối ưu hóa hơn.
    • Đọc thêm ở đâyđây!
  • Constructor trong thừa kế:
    • Lớp dẫn xuất không thừa kế constructor của lớp cơ sở bởi vì chúng ta không thể xác định chính xác cách mà các đối tượng của lớp dẫn xuất đc khởi tạo như nào(giả sử constructor đc đừa thừa kế và constructor đó nó thực hiện xử lý hay khởi tạo gì đấy trên lớp cha, mà constructor dùng để tạo object nên lớp thừa kế mà ko định nghĩa lại constructor thì object tạo ra có thể lỗi, đọc thêm ở đây!), nên kế thừa constructor có nghĩa là lớp dẫn xuất đc phép gọi đến constructor của lớp cơ sở.
    • Cả lớp cơ sở và lớp dẫn xuất đều chứa constructor mặc định. Bạn tạo object lớp dẫn xuất thì cả 2 constructor đó ở cả 2 lớp đều đc thự thi và constructor ở lớp cơ sở đc thực thi trc.
    • Nếu cả 2 lớp có constructor có tham số mà ở lớp cơ sở bạn ko chỉ định constructor mặc định thì trình biên dịch sẽ báo lỗi (Chỗ này mình ko hiểu tại sao nó lỗi, các bạn giải thích hộ t nhé! t đọc cách giải thích ở đây cũng bế tắc). Để khắc phục lỗi đó thì các bạn sử dụng từ khóa base.
    • Đọc thêm ở đây!

7.2 – Hàm hủy (Destructor)

  • Hàm hủy là một hàm bên trong class được sử dụng để xóa đi các đối tượng của class khi chúng không còn đc sử dụng để khôi phục (recover) không gian bộ nhớ, ngắt kết nối file I/O đc liên kết với đối tượng của lớp cần đc xóa…
  • Một vài chú ý:
    • Một class chỉ có duy nhất một hàm hủy và hàm hủy này đc gọi bởi Garbage collector của .Net Framework .
    • Hàm hủy ko có kiểu trả về, tham số, modifier (or Xem đầy đủ modifier có những thành phần nào trong cột trái ở đây!), có tên giống với tên class và có tiền tố “~” ở phía trước để phân biệt vs hàm tạo.
    • Hàm hủy chỉ đc sử dụng trong class còn trong struct thì ko, nó không thể overloaded(ghi đè) hoặc thừa kế.
  • Đọc thêm ở đâyđây!

8. Function Overloading

  • Là hàm dùng để ghi đè hàm đã có, các function overloading thì phải có cùng tên và kiểu trả về với hàm bị ghi đè(function overloaded), singnature khác nhau(số lượng tham số khác nhau hoặc kiểu dữ liệu của tham số khác nhau) của các hàm ghi đè với các hàm bị ghi đè trước đó.
  • Minh họa:

9. Interfaces

  • Định nghĩa: các bạn hiểu đơn giản như này, ông A, ông B, ông C… làm ăn với nhau, mấy ông này đều có 1 bản hợp đồng chung nó chứa các quy tắc, quy định mà ô nào cũng phải thực hiện, 1 interface nó như bản hợp đồng chứa các khai báo của các chức năng liên quan mà non-abstract class hoặc struct mà kề thừa Interfaces đều phải thực hiện các chức năng đó (tức là triển khai mở rộng cái chức năng đó trong class or struct, bạn xem chi tiết ở phần mình họa phía dưới).
  • Một interface có thể là thành viên của một namesapce or một class, các khai báo trong interface có thể chứa các khai báo của các thành viên sau: Methods, Properties, Indexers, Events.
  • Các khai báo trong interface thường là không có body, nhưng với C# bản 8.0 trở lên thì một thành viên có thể khai báo body, điều này đc gọi là “triển khai mặc định” và interface nó cung cấp triển khai mặc định đó cho class or struct không cung cấp triển khai cho thành viên đó (tức là không ghi đè thành viên đó).
  • Interface không chứa khai báo trường(field) có thể chứa các khai báo tĩnh của method, field, thuộc tính.
  • Interface không có thành viên nào là private, protected hoặc internal vì tất cả các thành viên trong interface mặc định là public và abstract.
  • Interface có thể thừa kế từ 1 hoặc nhiều interface, 1 class kế thừa 1 hoặc nhiều interface nhưng chỉ kế thừa đc 1 class.
  • Minh họa:
  • Tham khảo ở đây, đâyđây!

10. Reusability

Khi một class được tạo thì class này có thể được phân phối cho các lập trình viên khác sử dụng trong code của họ, điều này được gọi là reusability (tái sử dụng), hoặc theo thuật ngữ .Net thì khái niệm tái sử dụng này được gọi là một components hoặc một DLL (tức là để chỉ một class được tái sử dụng).

11. Partial classes

  • Một class đc trải trên nhiều file (Tức là chia một class thành nhiều phần, mỗi phần trên 1 file và trên mỗi phần đó có thuộc tính và phương thức thực hiện một chức năng nào đấy khác với những thằng còn lại trên các file khác đó).
  • Ưu điểm: ngắn gọn, rõ ràng (chức năng này cho ô nào viết), dễ dàng nâng cấp một chức năng nào đấy vì nó rõ ràng ?. Nhược điểm: nhiều file, dễ bị trùng lặp tên thuộc tính và phương thức, khó quản lý thuộc tính vì nó ở nhiều file.

12. Góp ý

Cảm ơn bạn đã đọc bài của mình, bài viết của mình có sai sót ở đâu, hiểu sai hay ntn thì mong các bạn góp ý để mình hoàn thiện thêm sao cho chuẩn nhất nhé, thank you!

13. Tài liệu tham khảo C#.

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/
https://www.c-sharpcorner.com/UploadFile/84c85b/object-oriented-programming-using-C-Sharp-net/
https://www.geeksforgeeks.org/c-sharp-tutorial/?ref=leftbar-rightbar#polymorphism
https://www.javatpoint.com/net-framework

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo