We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 42
C# Concepts
SOLID Principles C#: Solid Principles
• SOLID Principles SOLID is an acronym representing five
fundamental design principles in object-oriented programming (OOP) that aim to create more maintainable, understandable, and flexible software. • These principles were introduced by Robert C. Martin (Uncle Bob) and are widely regarded as best practices in software development. C#: Solid Principles
• Single Responsibility Principle (SRP): Classes should have
one reason to change. By injecting dependencies, each class focuses on its primary responsibility. • Open/Closed Principle (OCP): Classes should be open for extension but closed for modification. DI facilitates this by allowing new implementations to be introduced without altering existing classes. • Liskov Substitution Principle (LSP): Objects of a superclass should be replaceable with objects of a subclass. DI ensures that classes depend on abstractions, making substitution seamless. C#: Solid Principles
• Interface Segregation Principle (ISP): No client
should be forced to depend on methods it does not use. Using interfaces with DI ensures that classes only depend on the interfaces they need. • Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules; both should depend on abstractions. DI is a direct implementation of DIP. Solid Principles: Single Responsibility Principle (SRP)
• Definition: A class should have only one reason to
change, meaning it should have only one job or responsibility. • Explanation: • By ensuring that a class handles a single responsibility, you make your code easier to maintain and understand. • If a class has multiple responsibilities, changes in one responsibility might affect others, leading to bugs and increased complexity. Single Responsibility Principle – Example: Violation of SRP
public class Report
{ public void GenerateReport() { // Code to generate report } Single Responsibility Principle – Example: Violation of SRP public void SaveToFile(string path) { // Code to save report to file }
public void SendByEmail(string email)
{ // Code to send report via email } } Single Responsibility Principle – Example: Refactored With SRP
public class ReportGenerator
{ public void GenerateReport() { // Code to generate report } } Single Responsibility Principle – Example: Refactored With SRP
public class ReportSaver
{ public void SaveToFile(Report report, string path) { // Code to save report to file } } Single Responsibility Principle – Example: Refactored With SRP
public class ReportEmailer
{ public void SendByEmail(Report report, string email) { // Code to send report via email } } Solid Principles: Single Responsibility Principle (SRP) - Benefits • Maintainability: Easier to modify individual responsibilities.
• Testability: Each class can be tested
independently.
• Reusability: Classes with single responsibilities are
more reusable across different contexts. Solid Principles: Open/Closed Principle (OCP)
functions, etc.) should be open for extension but closed for modification. • Explanation: • One should be able to add new functionality to a class without altering its existing code. • This reduces the risk of introducing bugs into existing functionality when adding new features. Open/Closed Principle– Example: Violation of OCP
public class Rectangle
{ public double Width { get; set; } public double Height { get; set; } } Open/Closed Principle– Example: Violation of OCP public class AreaCalculator { public double CalculateArea(object shape) { if (shape is Rectangle rect) { return rect.Width * rect.Height; } throw new ArgumentException("Unknown shape"); } Open/Closed Principle– Example: Refactored of OCP
public interface IShape
{ double CalculateArea(); } Open/Closed Principle– Example: Refactored of OCP public class Rectangle : IShape { public double Width { get; set; } public double Height { get; set; }
public double CalculateArea()
{ return Width * Height; } } Open/Closed Principle– Example: Refactored of OCP public class Circle : IShape { public double Radius { get; set; }
public double CalculateArea()
{ return Math.PI * Radius * Radius; } } Open/Closed Principle– Example: Refactored of OCP public class AreaCalculator { public double CalculateArea(IShape shape) { return shape.CalculateArea(); } } Solid Principles: Open/Closed Principle (OCP) - Benefits
• Extensibility: Easily add new shapes without
modifying existing AreaCalculator.
• Maintainability: Reduces risk when introducing
new features.
• Encapsulation: Each shape knows how to calculate
its own area. Solid Principles: Liskov Substitution Principle (LSP)
• Definition: Objects of a superclass should be
replaceable with objects of a subclass without affecting the correctness of the program. • Explanation: • Subclasses should extend the base classes without changing their behavior. • This ensures that the derived classes can stand in for their base classes seamlessly. Liskov Substitution Principle – Example: Violation of LSP public class Bird { public virtual void Fly() { Console.WriteLine("Flying"); } } Liskov Substitution Principle – Example: Violation of LSP public class Ostrich : Bird { public override void Fly() { throw new NotImplementedException("Ostriches can’t fly"); } } Liskov Substitution Principle – Example: Refactored of LSP public interface IBird { void Eat(); }
public interface IFlyingBird : IBird
{ void Fly(); } Liskov Substitution Principle – Example: Refactored of LSP public class Sparrow : IFlyingBird { public void Eat() { Console.WriteLine("Sparrow eating"); }
public void Fly()
{ Console.WriteLine("Sparrow flying"); } Liskov Substitution Principle – Example: Refactored of LSP public class Ostrich : IBird { public void Eat() { Console.WriteLine("Ostrich eating"); } } Solid Principles: Liskov Substitution Principle (LSP) - Benefits
• Polymorphism: Subclasses can be used
interchangeably with their base interfaces.
• Robustness: Prevents unexpected behaviors when
using subclasses.
• Clear Contracts: Interfaces define clear
capabilities of classes. Solid Principles: Interface Segregation Principle (ISP)
• Definition: Clients should not be forced to depend on
interfaces they do not use. Instead of having large, "fat" interfaces, it's better to have smaller, more specific ones. • Explanation: • Breaking down interfaces into smaller, cohesive ones prevents implementing classes from being burdened with unnecessary methods, promoting cleaner and more understandable code. Interface Segregation Principle – Example: Violation of ISP public interface IMultiFunctionDevice { void Print(Document doc); void Scan(Document doc); void Fax(Document doc); } Interface Segregation Principle – Example: Violation of ISP ppublic class OldPrinter : IMultiFunctionDevice { public void Print(Document doc) { // Printing logic }
public void Scan(Document doc)
{ throw new NotImplementedException(); } Interface Segregation Principle – Example: Violation of ISP
public void Fax(Document doc)
{ throw new NotImplementedException(); } } Interface Segregation Principle – Example: Refactored of ISP public interface IPrinter { void Print(Document doc); }
• Definition: High-level modules should not depend on
low-level modules. Both should depend on abstractions (e.g., interfaces). Additionally, abstractions should not depend on details; details should depend on abstractions. • Explanation: • By depending on abstractions rather than concrete implementations, you promote loose coupling and enhance the flexibility and testability of your code. Dependency Inversion Principle – Example: Violation of DIP public class EmailService { public void SendEmail(string message) { // Send email logic } } Dependency Inversion Principle – Example: Violation of DIP
public class Notification
{ private EmailService _emailService = new EmailService();