0
0
Lập trình
Harry Tran
Harry Tran106580903228332612117

C# - Cách loại bỏ biểu thức switch hiệu quả

Đăng vào 2 tuần trước

• 8 phút đọc

Giới thiệu

Trong cộng đồng phát triển C#, có nhiều cuộc thảo luận xoay quanh việc loại bỏ biểu thức switch do những nhược điểm của nó. Nhiều lập trình viên đã nhận được phản hồi từ các pull request yêu cầu họ loại bỏ các biểu thức này. Mặc dù có những ý kiến trái chiều về việc sử dụng chúng, bài viết này sẽ không đi sâu vào việc phân tích lợi ích hay bất lợi của switch expressions. Thay vào đó, chúng ta sẽ khám phá cách tái cấu trúc mã nguồn để loại bỏ switch expressions nếu cần thiết.

Thiết lập mã

Đầu tiên, chúng ta sẽ tạo một ứng dụng console cơ bản để liên kết thói quen với thú cưng. Chúng ta sẽ thêm một lớp có tên là Habit:

csharp Copy
public class Habit
{
    public bool PlayFool { get; set; } = true;
    public bool Shy { get; set; } = true;
    public bool LoveColdShowers { get; set; } = true;
    public bool Lazy { get; set; } = false;
    public bool Bite { get; set; } = true;
    public bool Valid { get; set; } = true;
}

Lớp Habit bao gồm các thuộc tính boolean đơn giản như ShyLazy. Tiếp theo, chúng ta sẽ thêm một enum có tên là Pet:

csharp Copy
public enum Pet
{
    None,
    Cat = 1,
    Dog = 2,
    Rabbit = 3
}

Tiếp theo, chúng ta sẽ giới thiệu một lớp có tên PetsHabit chứa các phương thức công khai để lấy thói quen của thú cưng:

csharp Copy
public class PetsHabit
{
    public Habit MapHabitsUsingSwitch(Pet pet)
    {
        return pet switch
        {
            Pet.Dog => new Habit
            {
                LoveColdShowers = false,
                Shy = false
            },
            Pet.Cat => new Habit
            {
                LoveColdShowers = false,
                Lazy = true,
                Shy = false,
            },
            Pet.Rabbit => new Habit
            {
                PlayFool = false,
                Lazy = true,
            },
            _ => new Habit { Valid = false }
        };
    }
}

Lớp PetsHabit bao gồm phương thức MapHabitsUsingSwitch, nhận một tham số loại Pet. Phương thức này trả về thói quen của thú cưng và phụ thuộc vào một biểu thức switch để tạo ra một thói quen mới.

Tiếp theo, chúng ta sẽ tìm hiểu những cách tiếp cận khác để tái cấu trúc từ biểu thức switch mà vẫn giữ nguyên logic tương tự.

Tái cấu trúc biểu thức switch với If

Mặc dù chúng ta có thể tái cấu trúc biểu thức switch thành các câu lệnh if, nhưng đây không phải là lựa chọn tốt nhất. Tuy nhiên, vì mục đích khám phá, hãy xem xét cách chuyển đổi từ biểu thức switch thành các câu lệnh if.

Chúng ta sẽ thêm một phương thức khác có tên là MapHabitsUsingIf trong PetsHabit:

csharp Copy
public Habit MapHabitsUsingIf(Pet pet)
{
    if (pet is Pet.Dog)
    {
        return new Habit
        {
            LoveColdShowers = false,
            Shy = false
        };
    }

    if (pet is Pet.Cat)
    {
        return new Habit
        {
            LoveColdShowers = false,
            Lazy = true,
            Shy = false,
        };
    }

    if (pet is Pet.Rabbit)
    {
        return new Habit
        {
            PlayFool = false,
            Lazy = true,
        };
    }

    return new Habit { Valid = false };
}

Thay vì sử dụng biểu thức switch, MapHabitsUsingIf sử dụng các câu lệnh if để xác định thói quen của thú cưng. Rõ ràng, nếu chúng ta cần tái cấu trúc từ các biểu thức switch, việc thay thế chúng bằng các câu lệnh if không phải là giải pháp tối ưu. Cách tiếp cận này có thể gây ra những nhược điểm tương tự hoặc thậm chí tồi tệ hơn. Chúng ta cần tìm một phương pháp tốt hơn - hãy xem xét điều đó ở phần tiếp theo.

Tái cấu trúc biểu thức switch bằng Delegate

Có nhiều cách để tái cấu trúc các biểu thức switch, nhưng gợi ý phổ biến mà chúng ta thường gặp trực tuyến là sử dụng strategy pattern.

csharp Copy
public class PetsHabit
{
    public Habit MapHabitsUsingDelegate(Pet pet)
    {
        var habitsToFunctionMapper = GetHabitFunction(pet);

        if (habitsToFunctionMapper.TryGetValue(
             pet,
             out var getHabitFunction)
           )
        {
            return getHabitFunction();
        }
        return new Habit { Valid = false };
    }

    private Dictionary<Pet, Func<Habit>> GetHabitFunction(Pet pet)
    {
        return new Dictionary<Pet, Func<Habit>>
        {
            { Pet.Cat, this.GetCatHabit },
            { Pet.Dog, this.GetDogHabit },
            { Pet.Rabbit, this.GetRabbitHabit },
        };
    }
}
csharp Copy
private Habit GetCatHabit()
{
    return new Habit
    {
        LoveColdShowers = false,
        Lazy = true,
        Shy = false,
    };
}
csharp Copy
private Habit GetDogHabit()
{
    return new Habit
    {
        LoveColdShowers = false,
        Shy = false
    };
}
csharp Copy
private Habit GetRabbitHabit()
{
    return new Habit
    {
        PlayFool = false,
        Lazy = true,
    };
}

Thực hành tốt nhất

  • Sử dụng pattern thiết kế: Hãy cân nhắc sử dụng các pattern thiết kế như Strategy hoặc Factory để giúp mã nguồn dễ bảo trì hơn.
  • Giữ cho mã sạch: Nên tránh lặp lại mã. Nếu có nhiều logic tương tự, hãy tách chúng ra thành các phương thức riêng biệt.

Những cạm bẫy phổ biến

  • Quá phức tạp: Tái cấu trúc switch expressions thành các phương thức phức tạp hơn có thể làm mã khó hiểu hơn.
  • Hiệu suất: Đôi khi việc sử dụng if có thể làm giảm hiệu suất nếu số lượng điều kiện quá lớn.

Mẹo hiệu suất

  • Tránh lặp lại: Sử dụng các phương thức hoặc delegate để tránh lặp lại mã.
  • Kiểm tra hiệu suất: Luôn kiểm tra hiệu suất của mã sau khi tái cấu trúc để đảm bảo không có sự giảm sút.

Kết luận

Trong bài viết này, chúng ta đã xem xét cách loại bỏ biểu thức switch trong C# và các phương pháp thay thế mà không làm giảm hiệu suất hoặc khả năng bảo trì mã. Qua đó, việc hiểu rõ cách tái cấu trúc mã nguồn sẽ giúp các lập trình viên phát triển mã nguồn tốt hơn và dễ bảo trì hơn. Hãy thử áp dụng những kỹ thuật này trong dự án của bạn và chia sẻ kinh nghiệm với cộng đồng lập trình viên!

Câu hỏi thường gặp

  1. Khi nào nên sử dụng biểu thức switch?
    Biểu thức switch có thể hữu ích khi bạn có nhiều lựa chọn và muốn giữ mã nguồn gọn gàng. Tuy nhiên, hãy cẩn thận với các nhược điểm của nó.
  2. Có cách nào khác để thay thế biểu thức switch không?
    Có rất nhiều cách như sử dụng if statements, delegates, hoặc các pattern thiết kế khác.
  3. Tôi có nên loại bỏ hoàn toàn switch expressions khỏi mã của mình không?
    Không nhất thiết. Hãy đánh giá từng trường hợp cụ thể và quyết định dựa trên mức độ phức tạp và khả năng bảo trì.
Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào