DEV Community

mohamed Tayel
mohamed Tayel

Posted on

c# clean code: Guide to Defining and Structuring Classes

In C#, classes are the foundation of object-oriented programming (OOP), serving as templates for creating objects. This article provides a high-level look at what classes are, how they’re structured, and some best practices to keep your code clean and maintainable.

What is a Class?

A class in C# is a blueprint that defines the structure and behavior of objects. It can contain data members like fields, constants, and function members such as methods, properties, and events. Think of a class as a design that specifies what properties and methods an object will have.

For example, a Book class can represent the concept of a book, with properties such as Title and Author and methods like DisplayInfo to print the book's details.

Creating an Instance of a Class

To work with a class, you usually need to create an instance, or object, of that class. In C#, you use the new keyword to instantiate a class. The only exception to this rule is when the class is defined as static, in which case its members can be accessed directly without creating an instance.

Here’s how you would create an instance of the Book class:

Book myBook = new Book("The Great Gatsby", "F. Scott Fitzgerald");
myBook.DisplayInfo(); // Output: Title: The Great Gatsby, Author: F. Scott Fitzgerald
Enter fullscreen mode Exit fullscreen mode

Key Components of a Class

  1. Class Signature
    • The class signature is a unique identifier that includes an access modifier (e.g., public, private, internal) to specify accessibility, the class keyword, and the class name:
   public class Book
   {
       // Class body goes here
   }
Enter fullscreen mode Exit fullscreen mode
  1. Fields and Properties

    • Fields: These are private variables used to store data in a class. For example, a Book class might have a private field for title.
    • Properties: Properties provide controlled access to fields, allowing you to set or retrieve values while enforcing validation or other logic:
     public string Title
     {
         get => _title;
         set
         {
             if (string.IsNullOrWhiteSpace(value))
                 throw new ArgumentException("Title cannot be empty or null.");
             _title = value;
         }
     }
    
  • Properties like this are beneficial for protecting data and enforcing rules.
  1. Constructors

    • Constructors initialize a class’s fields when an instance is created. A class can have multiple constructors with different parameters, allowing for flexibility in instantiation:
     public Book(string title, string author)
     {
         Title = title;
         Author = author;
     }
    
  • Best Practices for Constructors:
    • Provide a default constructor if the class might need to be instantiated without any parameters.
    • Use parameterized constructors for classes that require specific values at the time of creation.
    • Avoid complex logic in constructors to keep instantiation efficient and manageable.
  1. Methods

    • Methods define actions or behaviors that an object can perform. For example, a Book class might have a DisplayInfo method to show book details:
     public void DisplayInfo()
     {
         Console.WriteLine($"Title: {Title}, Author: {Author}");
     }
    

Best Practices for Designing Classes

To create classes that are easy to maintain and extend, follow these guidelines:

  1. Encapsulation: Use properties to control access to fields, making data only accessible or modifiable in a controlled way.
  2. Organize Members: Arrange fields, properties, constructors, and methods in a consistent order to improve readability.
  3. Clear Naming: Use descriptive names for classes, properties, and methods to make your code easy to understand.
  4. Single Responsibility Principle: Keep each class focused on a single responsibility. If a class seems to be doing too much, consider breaking it down into smaller, more focused classes.

Example Class: Book

Here’s the Book class with all these components put together:

public class Book
{
    // Private field for the book's title
    private string _title;

    // Property to encapsulate the title field with validation
    public string Title
    {
        get => _title;
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("Title cannot be empty or null.");
            _title = value;
        }
    }

    // Read-only property for the author, set in the constructor
    public string Author { get; }

    // Constructor to initialize both title and author
    public Book(string title, string author)
    {
        Title = title;
        Author = string.IsNullOrWhiteSpace(author) 
                 ? throw new ArgumentException("Author cannot be empty or null.") 
                 : author;
    }

    // Method to display book information
    public void DisplayInfo()
    {
        Console.WriteLine($"Title: {Title}, Author: {Author}");
    }
}
Enter fullscreen mode Exit fullscreen mode

This Book class demonstrates several important principles:

  • Encapsulation: Fields are private, with public properties controlling access.
  • Read-only Property: The Author property is read-only, making the author immutable after the object is created.
  • Validation: Both Title and Author properties enforce validation to prevent invalid data.
  • Well-Structured Methods: The DisplayInfo method provides a clear, simple way to access data stored in the class.

Conclusion

Classes are a core part of C# and OOP. By structuring them carefully and following best practices, you can create robust, maintainable, and reusable code. Keeping your classes focused and properly encapsulated will help ensure a solid foundation for any C# application.

Top comments (1)

Collapse
 
programmerraja profile image
Boopathi

This is a great introduction to defining and structuring classes in C#. The example of the Book class is very helpful, showing how to implement encapsulation, validation, and clear methods.