Functional vs OOP in C#: What to Choose in 2025?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Two Sides of the Same Coin

\n\n

Imagine you are building a house. You can take ready-made blocks (classes, objects, inheritance) and assemble a complex structure from them — this is object-oriented programming (OOP). Or you can think like a mathematician: "I take data, apply a pure function to it, and get a new result without changing anything" — this is functional programming.

\n\n

In C#, both paradigms coexist in an amazing way. And if you write in this language, sooner or later you will ask yourself: "What if I'm doing this wrong? Maybe I should use more LINQ and fewer classes?"

\n\n

In this article, we won't argue about which is better. We will figure out how the functional approach differs from OOP in C#, when each one really helps, and when it hinders. And yes, there will be a lot of code. Let's go!

\n\n

1. OOP in C#: The Classic That Works

\n\n

Object-oriented programming is about state and behavior. You have a class that stores data (fields, properties) and methods that modify that data.

\n\n

Example: an application for managing orders in an online store.

\n\n
public class Order\n{\n    public int Id { get; set; }\n    public List<string> Items { get; private set; }\n    public decimal TotalPrice { get; private set; }\n\n    public Order(int id)\n    {\n        Id = id;\n        Items = new List<string>();\n        TotalPrice = 0;\n    }\n\n    public void AddItem(string itemName, decimal price)\n    {\n        Items.Add(itemName);\n        TotalPrice += price;\n    }\n\n    public void ApplyDiscount(decimal percent)\n    {\n        TotalPrice -= TotalPrice * (percent / 100);\n    }\n}
\n\n

What do we see? Encapsulation: TotalPrice cannot be changed directly — only through methods. State of the object changes over time: we add items, apply discounts. This is pure OOP.

\n\n

Pros of OOP in C#

\n
    \n
  • Understandable real-world model: Order, Customer, Product — everything is like in real life.
  • \n
  • Reusability through inheritance and interfaces.
  • \n
  • Complexity management by breaking it down into small objects.
  • \n
\n\n

Cons of OOP

\n
    \n
  • Side effects: one method can change state, and you easily lose control.
  • \n
  • Testing complexity: you need to create objects, mock dependencies.
  • \n
  • Redundancy: sometimes it's easier to write a function than to create a whole class.
  • \n
\n\n

2. Functional Approach in C#: LINQ and Beyond

\n\n

Functional programming is about pure functions (without side effects) and immutability of data. In C#, it is especially noticeable in LINQ, lambda expressions, and working with collections.

\n\n

Let's solve the same problem — managing an order — but functionally.

\n\n
// Immutable record\npublic record Order(int Id, List<string> Items, decimal TotalPrice);\n\npublic static class OrderFunctions\n{\n    public static Order AddItem(Order order, string item, decimal price)\n    {\n        var newItems = order.Items.Append(item).ToList();\n        return order with { Items = newItems, TotalPrice = order.TotalPrice + price };\n    }\n\n    public static Order ApplyDiscount(Order order, decimal percent)\n    {\n        return order with { TotalPrice = order.TotalPrice * (1 - percent / 100) };\n    }\n}\n\n// Usage\nvar order = new Order(1, new List<string>(), 0);\norder = OrderFunctions.AddItem(order, "Laptop", 50000);\norder = OrderFunctions.ApplyDiscount(order, 10);
\n\n

Notice? We are not changing the original object. A new instance is created each time using with. This eliminates accidental changes.

\n\n

And

Blogs

Book Recommendations