Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Khác biệt giữa List và IList trong C#

Tóm tắt cốt lõi

Đặc điểmList<T>IList<T>
Bản chấtClass (concrete implementation)Interface (contract)
Khởi tạonew List<T>()Không thể new IList<T>()
Kế thừaImplements: IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerableKế thừa: ICollection<T>, IEnumerable<T>
Phương thức mở rộngCó thêm: AddRange, RemoveAll, Find, Sort, Reverse, BinarySearch, ConvertAll, GetRange, AsReadOnly, Capacity, TrimExcessChỉ các method interface cơ bản
PerformanceTruy cập index nhanh (O(1)), cache-friendlyTruy cập qua interface (virtual call, chậm hơn nhẹ)

Code minh họa


using System;
using System.Collections.Generic;

class Demo 
{
    static void Main() 
    {
        // ❌ SAI: Không thể khởi tạo interface
        // IList list = new IList(); // Compile Error
        
        // ✅ ĐÚNG: Khai báo interface, khởi tạo concrete class
        IList ilist = new List();
        ilist.Add("Mark");
        ilist.Add("John");
        
        // ✅ ĐÚNG: Dùng concrete class trực tiếp
        List list = new List();
        list.Add("Mark");
        list.Add("John");
        
        // List có method mở rộng mạnh hơn
        list.AddRange(new[] { "Alice", "Bob" });
        list.RemoveAll(s => s.StartsWith("M"));
        list.Sort();
        
        // IList chỉ có method cơ bản
        // ilist.AddRange(...); // ❌ Không compile
        // ilist.Sort();        // ❌ Không compile
        
        // Ép kiểu nếu cần method List
        if (ilist is List concreteList) 
        {
            concreteList.Sort();
        }
    }
}

Khi nào dùng List vs IList?

Dùng List<T> khi:

  • Implementation nội bộ (private field, local variable).
  • Cần method đặc thù: Sort, Find, BinarySearch, Capacity, TrimExcess.
  • Performance critical (tránh virtual call overhead).
  • Return type của private/internal method.

Dùng IList<T> khi:

  • Public API (return type, parameter type) - Program to interface.
  • Cho phép thay đổi implementation sau này (List → Array, ImmutableList, CustomList).
  • Dependency Injection, Repository pattern.
  • Chỉ cần các operation cơ bản: Add, Remove, Indexer, Count, Contains.

Best Practice: API Design


// ❌ Trả về concrete type - tight coupling
public List GetUsers() { ... }

// ✅ Trả về interface - loose coupling
public IList GetUsers() { ... }
public IReadOnlyList GetUsers() { ... } // Tốt hơn: immutable intent

// Parameter: nhận interface rộng nhất có thể
public void ProcessItems(IEnumerable items) { ... } // Chỉ đọc
public void ProcessItems(ICollection items) { ... } // Cần Count, Add/Remove
public void ProcessItems(IList items) { ... }       // Cần indexer, Insert

IReadOnlyList<T> - Lựa chọn tốt hơn cho Read-only


// .NET 4.5+ - Chỉ đọc, không Add/Remove
public IReadOnlyList GetUsers() 
{
    return _users.ToList(); // hoặc _users.AsReadOnly()
}

// List implement IReadOnlyList
List list = new() { "a", "b" };
IReadOnlyList ro = list; // Implicit conversion
// ro.Add("c"); // ❌ Compile error

Array vs List vs IList

  • T[] implement IList<T> (nhưng Add/Remove throw NotSupportedException - fixed size).
  • List<T> implement IList<T> (dynamic size).
  • IList<T> là abstraction chung cho cả hai.

Performance Tip


// Tránh boxing/unboxing với value types
List list = new List();     // Good: int lưu trực tiếp
IList ilist = new List();   // OK: nhưng gọi qua interface virtual
IEnumerable enum = list;         // OK: nhưng iterator pattern

// Benchmark: List nhanh hơn IList ~5-10% do devirtualization