C# interview questions: SOLID Principles in C#

SOLID Principles in C# (SOLID 原则在 C# 中的应用)

SOLID is an acronym for five design principles that help developers create more maintainable, flexible, and scalable code. These principles are foundational to object-oriented design and help improve software quality.
SOLID 是五个设计原则的缩写,这些原则帮助开发者编写更易维护、灵活且可扩展的代码。它们是面向对象设计的基础,有助于提升软件质量。


1. S – Single Responsibility Principle (单一职责原则)

Definition: A class should have only one reason to change, meaning it should have one job or responsibility.
定义:一个类应该只有一个引起它变化的原因,也就是说,它应该只有一个职责。

This principle ensures that a class has one specific function, making the code easier to maintain and modify.
这个原则确保一个类只有一个特定的功能,使代码更易维护和修改。

Example (示例):

Violation:

public class OrderProcessor
{
    public void ProcessOrder(Order order)
    {
        // Processing order
        LogOrder(order);  // Logging responsibility
    }
}

In this case, the OrderProcessor class has two responsibilities: processing orders and logging, violating SRP.
在这个例子中,OrderProcessor 类承担了两个职责:处理订单和日志记录,违反了 SRP。

Refactor:

public class OrderProcessor
{
    private readonly ILogger _logger;

    public OrderProcessor(ILogger logger)
    {
        _logger = logger;
    }

    public void ProcessOrder(Order order)
    {
        _logger.Log(order);
    }
}

Here, the logging responsibility is moved to a separate class.
这里,将日志记录的职责移到了一个单独的类中。


2. O – Open/Closed Principle (开闭原则)

Definition: Software entities should be open for extension but closed for modification.
定义:软件实体应该对扩展开放,但对修改关闭。

This means you should be able to add new functionality without modifying existing code.
这意味着你可以添加新功能,而无需修改现有代码。

Example (示例):

Violation:

public class PaymentProcessor
{
    public void ProcessPayment(string paymentType)
    {
        if (paymentType == "CreditCard")
        {
            // Process credit card
        }
        else if (paymentType == "PayPal")
        {
            // Process PayPal
        }
    }
}

In this case, adding a new payment type requires modifying the class, violating OCP.
在这个例子中,添加一种新的支付类型需要修改类,违反了 OCP。

Refactor:

public interface IPayment
{
    void Process();
}

public class CreditCardPayment : IPayment
{
    public void Process()
    {
        // Process credit card payment
    }
}

public class PaymentProcessor
{
    public void ProcessPayment(IPayment payment)
    {
        payment.Process();
    }
}

Now, new payment methods can be added without modifying the existing class.
现在,可以添加新的支付方式而不需要修改现有类。


3. L – Liskov Substitution Principle (里氏替换原则)

Definition: Objects of a base class should be replaceable with objects of derived classes without affecting the program’s correctness.
定义:基类的对象应该可以被其子类对象替换,而不会影响程序的正确性。

This ensures that subclasses extend the functionality of a base class without changing its behavior.
这确保子类扩展了基类的功能,而不改变其行为。

Example (示例):

Violation:

public class Bird
{
    public virtual void Fly()
    {
        Console.WriteLine("Flying");
    }
}

public class Penguin : Bird
{
    public override void Fly()
    {
        throw new Exception("Penguins cannot fly!");
    }
}

Here, Penguin breaks LSP by changing the expected behavior of Fly().
在这里,Penguin 通过改变 Fly() 的预期行为,违反了 LSP。

Refactor:

public interface IFlyable
{
    void Fly();
}

public class Sparrow : IFlyable
{
    public void Fly()
    {
        Console.WriteLine("Flying");
    }
}

public class Penguin
{
    // Penguins don't implement IFlyable
}

Now, Penguin does not need to override Fly().
现在,Penguin 不需要重写 Fly()


4. I – Interface Segregation Principle (接口隔离原则)

Definition: No client should be forced to depend on methods it does not use.
定义:客户端不应被迫依赖它不需要的方法。

Instead of one large interface, create multiple smaller, more specific interfaces.
与其使用一个大的接口,不如创建多个较小的、更具体的接口。

Example (示例):

Violation:

public interface IWorker
{
    void Work();
    void Eat();
}

public class RobotWorker : IWorker
{
    public void Work() { /* Work implementation */ }
    public void Eat() { throw new NotImplementedException(); }
}

The RobotWorker class is forced to implement the Eat() method, even though it doesn’t need it.
RobotWorker 类被迫实现 Eat() 方法,即使它不需要。

Refactor:

public interface IWorker
{
    void Work();
}

public interface IEater
{
    void Eat();
}

public class RobotWorker : IWorker
{
    public void Work() { /* Work implementation */ }
}

Now, RobotWorker only implements the methods it needs.
现在,RobotWorker 只实现了它需要的方法。


5. D – Dependency Inversion Principle (依赖倒置原则)

Definition: High-level modules should not depend on low-level modules. Both should depend on abstractions.
定义:高层模块不应依赖于低层模块,二者都应依赖于抽象。

This principle promotes loose coupling between components.
这个原则促进了组件之间的松耦合。

Example (示例):

Violation:

public class EmailService
{
    public void SendEmail(string message)
    {
        // Send email
    }
}

public class Notification
{
    private EmailService _emailService = new EmailService();

    public void SendNotification(string message)
    {
        _emailService.SendEmail(message);
    }
}

The Notification class is tightly coupled to the EmailService.
Notification 类与 EmailService 紧密耦合。

Refactor:

public interface IMessageService
{
    void SendMessage(string message);
}

public class EmailService : IMessageService
{
    public void SendMessage(string message)
    {
        // Send email
    }
}

public class Notification
{
    private readonly IMessageService _messageService;

    public Notification(IMessageService messageService)
    {
        _messageService = messageService;
    }

    public void SendNotification(string message)
    {
        _messageService.SendMessage(message);
    }
}

Now, Notification depends on the abstraction IMessageService, promoting loose coupling.
现在,Notification 依赖于抽象 IMessageService,促进了松耦合。


Conclusion (总结)

The SOLID principles help in designing better object-oriented software by making it more flexible, maintainable, and scalable. Following these principles ensures that your code remains easy to extend and maintain over time.
SOLID 原则通过使软件更加灵活、可维护和可扩展,帮助设计更好的面向对象软件。遵循这些原则可以确保你的代码在长期内易于扩展和维护。

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *