Dependency Inversion Principle (DIP) in C#

In my previous articles I wrote about Solid Principles in C#.

In this article, I am going to show you when and how to use the Dependency Inversion Principle (DIP) in C# with an example project. You can find the repository on GitHub.

The master branch shows the initial code used in the example.  There are separate tags and branches for each of the all solid principles that you can review or download as well. Here are links you can use to jump to these tagged versions in your browser:

What is the Dependency Inversion Principle (DIP) in C#?

The Dependency Inversion Principle (DIP) is the last, in alphabetical order, of the SOLID design principles. We can always reuse the definition from Wikipedia.

High-level modules should not import anything from low-level modules. Both should depend on abstractions.

Abstractions should not depend on details. Details should depend on abstractions.

Let’s try to summarize these two definitions:

  • Instead of high-level modules relying directly on low-level modules, both should communicate through abstract interfaces. This promotes flexibility and allows for easier substitution of components.
  • Abstractions should not be tightly coupled to specific implementations; instead, the concrete details should adhere to the abstractions. This allows you to change or extend implementations without affecting the overall structure of your code.

Abstractions describe what:

  • Send a message;
  • Store a record;

Details specify how to do:

  • Send a push notification to a device;
  • Deserialize an object and store in a database;

In this example we expose implementation details and making the interface much less reusable. The interface should not know the details of the database, in this case mysql.

public interface IOrderDataAccess
{
    MySqlDataReader GetOrders(MySqlParameterCollection params);
}

This example hide the details above and make the interface reusable.

public interface IOrderDataAccess
{
    List<Order> GetOrders(Dictionary<string, string> params);
}

Continue reading

Interface Segregation Principle (ISP) in C#

In my previous articles I wrote about Solid Principles in C#.

In this article, I am going to show you when and how to use the Interface Segregation Principle in C# with an example project. You can find the repository on GitHub.

The master branch shows the initial code used in the example.  There are separate tags and branches for each of the all solid principles that you can review or download as well. Here are links you can use to jump to these tagged versions in your browser:

What is the Interface Segregation Principle (ISP) in C#?

The Interface Segregation Principle is the fourth of the SOLID design principles. Let us take a look at Robert C. Martin’s definition and try to analyse it.

Clients should not be forced to depend on methods that they do not use.

What’s a Client?

It’s the calling code. It’s the code that is interacting with an instance of the interface.

What does Interface mean in C# for the Interface Segregation Principle (ISP)?

In C# we have two kinds of interfaces described by the ISP.

A type’s interface is whatever can be accessed by a client.

Ok nice description but in the end what do we have to do?

Prefer small and related interfaces to fat ones.

Continue reading

Open Closed Principle (OCP) in C#

In my previous articles I wrote about Solid Principles in C# and the Single Responsibility Principle.

In this article, I am going to show you when and how to use the Open Closed Principle in C# with an example project. You can find the repository on GitHub.

The master branch shows the initial code used in the example.  There are separate tags and branches for each of the all solid principles that you can review or download as well. Here are links you can use to jump to these tagged versions in your browser:

What is the Open Closed Principle (OCP) in C#?

The Open Closed Principle is one of the SOLID design principles. We can always reuse the definition from Wikipedia.

The Open Closed Principle states software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

So these software entities should be:

  • Open For Extension This means that the behavior of the module can be extended, for example we could add fields or new elements in the functions with a fixed behavior,
  • Closed for Modification The source code of such a module is inviolate. No one is allowed to make source code changes to it.

Why should you use the Open Closed Principle (OCP)?

  • Application robust. Don’t break existing code, prefer implementing new features in new classes, follow the SRP, no need to change tested class and less bug.
  • Flexible. Working with interfaces, it’s easy to accommodate new requirements and this reduces the cost of a business change requirement.
  • Better testability. Easy to test and less error prone.

Continue reading

Type Conversion in C#

Type Conversion

The process of converting one type to another is called type conversion. In C#, you can perform the following kinds of conversions:

  • Implicit conversions
  • Explicit conversions
  • User-defined conversions
  • Conversion with a helper class

To go more in detail about Implicit and Explicit conversions read my previous article Boxing and Unboxing in C#.

Implicit conversions

An implicit conversion doesn’t need any special syntax, it can be executed because the compiler knows that the conversion is allowed and that it’s safe to convert.

A value type such as int can be stored as a double because an int can fit inside a double without losing any precision or from a reference type to one of its base types.

In this example, num is int and will be converted to double and no data will be lost.

int num = 123456;
double bigNum = num;
Console.WriteLine("bigNum: {0}", bigNum); 
/* Output:
    bigNum: 123456
*/

Also for reference types, no special syntax is necessary because a derived class always contains all the members of a base class. In these cases, the cast is done implicitly by the compiler.

Rectangle rectangle = new Rectangle();
Shape shape = rectangle;

Continue reading

Boxing and Unboxing in C#

C# is, for the most part, a statically typed language, this means that the compiler will check the type of every expression and you sometimes have to convert between types. The concept of boxing and unboxing is the starting point in C# type system in which a value of any type can be treated as an object.

As mentioned in my previous article C# Difference between Struct and Class, the important difference between a value type and a reference type is that the value type stores its value directly. A reference type stores a reference that points to an object on the heap that contains the value.

Boxing and Unboxing in C#

Boxing

Boxing is the process of taking a value type, putting it inside a new object on the heap and storing a reference to it on the stack. Boxing is an implicit conversion.

public class Program
{
    public static void Main(string[] args)
    {
        int total = 1976;
        object obj = total; // Boxing

        total = 2020;  

        System.Console.WriteLine("The value-type value = {0}", total); 
        System.Console.WriteLine("The reference-type value = {0}", obj); 
    } 
} 
/* Output: 
    The value-type value = 2020 
    The reference-type value = 1976 
*/

Unboxing

Unboxing is the exact opposite, it takes the item from the heap and returns a value type that contains the value from the heap. Unboxing is an explicit conversion. Attempting to unbox null or to unbox a reference to an incompatible value type causes an Exception.

public class Program
{
    public static void Main(string[] args)
    {
        int total = 1976;
        object obj = total;  // Boxing
        
        total = (int)obj; // Unboxing
        System.Console.WriteLine("The value-type value = {0}", total); 
        System.Console.WriteLine("The reference-type value = {0}", obj); 
    } 
} 
/* Output: 
    The value-type value = 1976 
    The reference-type value = 1976 
*/

Performance

There are some performance implications and memory requirements with each box and unboxing operation. When using the non-generic collections to store a value type, the boxing and unboxing operations can hurt performance.

Thanks for reading! 🌟

Difference between Struct and Class in C#

A good understanding of the differences in the behaviour of a Class and a Struct is crucial in creating a good software and developing in csharp.

Struct

A Struct is a value type that is typically used to encapsulate small groups of related variables and it is suitable for representing lightweight objects.

public struct Point 
{ 
    public int x;
    public int y; 
}

Class

A class is a reference type that enables to create your own custom types by grouping together variables of other types, methods and events. It defines the data and behaviour of a type.

public class Person 
{ 
    public string name;
    public Person() 
    { 
        name = "Steve"; 
    }
}

In .NET there are two locations in which a type can be stored in memory:

  • Stack;
  • Heap;

Stack

Value types are stored in the stack.

In this example, we create a variable int a = 3, after a variable int b = 4. On the stack, each variable is stored in the order it was created. In the end, we create a variable int c = b with the same value of b. So they both have 4 as value. For value types, each variable stores its own data.

Heap

The value of a reference type is stored on the heap and the address to this value is stored on the stack.

In this example, we create a class Student with a field name. Then we create an instance of the class Student called a and we set the value name to Alex. In the stack we store variable a and its value Alex on the heap. In the Stack, we store a pointer to the data. After we create another instance of the class Student called and we set the value name to Steve. In the Stack, we store variable b and its value Steve on the heap. Then we create another object called c and we set to b, in the stack we store variable c but its address is the same of b. If we change c name to Robert we are also changing the value of b that now is Robert and not Steve.

Memory

The benefit of storing data on the stack is that it’s faster, smaller, and doesn’t need the attention of the garbage collector, required for the heap. Value types are on the stack most of the time and are freed when the current method ends.

Reference types are on the heap and managed by the garbage collector. When a value type is on the stack, it takes up less memory than it would on the heap.

Difference

These are the main difference between Struct and Class in C#:

Difference between Struct and Class in C#

Tips

Microsoft suggests using a Struct instead of a Class if :

Instances of the type are small and commonly short-lived.

and to avoid Struct if:

It will have to be boxed frequently.

It isn’t immutable.

It has not an instance size under 16 bytes.

It logically doesn’t represent a single value, similar to primitive types.

Thanks for reading! 🌟