How to implement Single Responsibility Principle using C#?

The Single Responsibility Principle (SRP) is the first principle of SOLID design principles in object-oriented programming. It states that a class should have only one reason to change, meaning each class should handle a single responsibility or concern.

In this context, responsibility is considered to be one reason to change. When a class has multiple responsibilities, changes to one responsibility can affect the other functionality, making the code harder to maintain and test.

Definition

The Single Responsibility Principle states that if we have two reasons to change a class, we should split the functionality into two separate classes. Each class will handle only one responsibility, and future changes will be made only in the class that handles the specific concern.

Single Responsibility Principle Violates SRP One class handles: ? Email validation ? Name validation ? Email sending Multiple reasons to change Follows SRP Separate classes: ? EmailService ? UserNameService ? InviteService Single responsibility each

Benefits of Following SRP

  • Maintainability: Changes to one functionality don't affect others

  • Testability: Each class can be tested independently

  • Reusability: Single-purpose classes can be reused in different contexts

  • Reduced coupling: Classes have fewer dependencies on each other

Code Before Single Responsibility Principle

The following example shows a class that violates SRP by handling multiple responsibilities −

using System;
using System.Net.Mail;

namespace SolidPrinciples.Single.Responsibility.Principle.Before {
    class Program {
        public static void SendInvite(string email, string firstName, string lastname) {
            // Name validation responsibility
            if(String.IsNullOrWhiteSpace(firstName) || String.IsNullOrWhiteSpace(lastname)) {
                throw new Exception("Name is not valid");
            }
            
            // Email validation responsibility
            if (!email.Contains("@") || !email.Contains(".")) {
                throw new Exception("Email is not Valid!");
            }
            
            // Email sending responsibility
            SmtpClient client = new SmtpClient();
            client.Send(new MailMessage("Test@gmail.com", email) { Subject="Please Join the Party!" });
        }
        
        public static void Main(string[] args) {
            try {
                SendInvite("john@example.com", "John", "Doe");
                Console.WriteLine("Invite sent successfully!");
            }
            catch(Exception ex) {
                Console.WriteLine("Error: " + ex.Message);
            }
        }
    }
}

The output of the above code is −

Invite sent successfully!

Code After Single Responsibility Principle

Here's the refactored code following SRP, where each class has a single responsibility −

using System;
using System.Net.Mail;

namespace SolidPrinciples.Single.Responsibility.Principle.After {
    internal class Program {
        public static void SendInvite(string email, string firstName, string lastname) {
            UserNameService.Validate(firstName, lastname);
            EmailService.Validate(email);
            InviteService.Send(email);
        }
        
        public static void Main(string[] args) {
            try {
                SendInvite("john@example.com", "John", "Doe");
                Console.WriteLine("Invite sent successfully!");
            }
            catch(Exception ex) {
                Console.WriteLine("Error: " + ex.Message);
            }
        }
    }
    
    public static class UserNameService {
        public static void Validate(string firstname, string lastName) {
            if (string.IsNullOrWhiteSpace(firstname) || string.IsNullOrWhiteSpace(lastName)) {
                throw new Exception("Name is not valid");
            }
        }
    }
    
    public static class EmailService {
        public static void Validate(string email) {
            if (!email.Contains("@") || !email.Contains(".")) {
                throw new Exception("Email is not Valid!");
            }
        }
    }
    
    public static class InviteService {
        public static void Send(string email) {
            SmtpClient client = new SmtpClient();
            client.Send(new MailMessage("Test@gmail.com", email) { Subject = "Please Join the Party!" });
        }
    }
}

The output of the above code is −

Invite sent successfully!

Comparison

Before SRP After SRP
One method handles validation and sending Separate services for each concern
Hard to test individual validations Each service can be tested independently
Changes affect multiple functionalities Changes are isolated to specific services
Tight coupling of responsibilities Loose coupling with clear separation

Conclusion

The Single Responsibility Principle improves code maintainability by ensuring each class has only one reason to change. By separating concerns into dedicated classes, we create more testable, reusable, and maintainable code that follows good object-oriented design practices.

Updated on: 2026-03-17T07:04:36+05:30

414 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements